Browse Source

Fix introduced regressions.

pgenutil.pas, generate_specialization:
* If we are parsing the result type of a function or operator that belongs to a generic (parse_generic is true) we need to accept also "_LT" and "_GT" as for this the "block_type" is NOT set to one of "bt_type", "bt_var_type", "bt_const_type" and only there "_LSHARPBRACKET" and "_RSHARPBRACKET" are returned by the scanner. This is part of the fix for webtbs\tw18567.pp.
* In non—Delphi modes if we encounter a specialization of the currently parsed class/record (using "specialization"!) the given "tt" will be an errordef (because the def of the generic's symbol was not yet set to "current_structdef"). To solve this we check in this case whether the calculated generic name is equal to that of the "current_structdef" and simply return that as specialized def. This fixes test\tgeneric11.pp.
* When searching for the generic symbol search if the generic belongs to a class or record then we need to search for it in the class or record. This fixes webtbs\tw16090.pp.

ptype.pas
* parse_nested_types: We now return the generic defs for specializations inside generics instead of an undefined def, so we must also parse nested type usages correctly, so that type checks don't fail (undefined defs circumvent them mostly). This fixes webtbs\tw10247.pp.
* single_type: We need to allow _LT as an indication for a Delphi specialization as return types are parsed with block_type not in "bt_type", "bt_var_type", "bt_const_type". This is also a fix a part of the fix for webtbs\tw18567.pp.
* read_named_type, expr_type:
Fixes for test\tgeneric17.pp and test\tgeneric22.pp:
(a) In non-Delphi modes we might encounter usages of the generic dummy symbol inside the generic class belonging to it. This is basically a specialization, but as the reference from the dummy symbol to the "current_structdef" is not yet established (this is done after "read_named_type" in "types_dec" returns) we need to use other ways to check for the valid use of the dummy symbol (basically we check whether the name of the dummy symbol and the name of the current_structdef without the type count match)
(b) For specializations we can check whether the genericdef of the currently parsed structdef (the specialization) is the same as the typedef of the encountered dummy symbol.

pexpr.pas, factor, factor_read_id:
Fixes for test\tgeneric17.pp and test\tgeneric22.pp:
To allow the mentioned fixes in ptype for the same tests to be usable at all we must not return an "identifier not found" error if we encounter such a valid use of a generic dummy symbol.

git-svn-id: branches/svenbarth/generics@19719 -
svenbarth 13 years ago
parent
commit
6a83ebc4a5
3 changed files with 62 additions and 13 deletions
  1. 11 1
      compiler/pexpr.pas
  2. 22 4
      compiler/pgenutil.pas
  3. 29 8
      compiler/ptype.pas

+ 11 - 1
compiler/pexpr.pas

@@ -2150,7 +2150,17 @@ implementation
                    assigned(ttypesym(srsym).typedef) and
                    (ttypesym(srsym).typedef.typ=undefineddef) and
                    not (sp_generic_para in srsym.symoptions) and
-                   not (token in [_LT, _LSHARPBRACKET])) then
+                   not (token in [_LT, _LSHARPBRACKET]) and
+                   not (
+                     { in non-Delphi modes the generic class' name without a
+                       "specialization" or "<T>" may be used to identify the
+                       current class }
+                     (sp_generic_dummy in srsym.symoptions) and
+                     assigned(current_structdef) and
+                     (df_generic in current_structdef.defoptions) and
+                     not (m_delphi in current_settings.modeswitches) and
+                     (upper(srsym.realname)=copy(current_structdef.objname^,1,pos('$',current_structdef.objname^)-1))
+                   )) then
                  begin
                    identifier_not_found(orgstoredpattern);
                    srsym:=generrorsym;

+ 22 - 4
compiler/pgenutil.pas

@@ -60,6 +60,7 @@ uses
         st  : TSymtable;
         srsym : tsym;
         pt2 : tnode;
+        found,
         first,
         err : boolean;
         i,
@@ -98,14 +99,16 @@ uses
           for recording in genericbuf }
         if parse_generic then
           begin
-            consume(_LSHARPBRACKET);
+            if not try_to_consume(_LT) then
+              consume(_LSHARPBRACKET);
             gencount:=0;
             repeat
               pt2:=factor(false,true);
               pt2.free;
               inc(gencount);
             until not try_to_consume(_COMMA);
-            consume(_RSHARPBRACKET);
+            if not try_to_consume(_GT) then
+              consume(_RSHARPBRACKET);
             { we need to return a def that can later pass some checks like
               whether it's an interface or not }
             if parse_generic and (not assigned(tt) or (tt.typ=undefineddef)) then
@@ -131,6 +134,12 @@ uses
                         exit;
                       end;
                     tt:=ttypesym(srsym).typedef;
+                    { this happens in non-Delphi modes if we encounter a
+                      specialization of the generic class or record we're
+                      currently parsing }
+                    if (tt.typ=errordef) and assigned(current_structdef) and
+                        (current_structdef.objname^=ugenname) then
+                      tt:=current_structdef;
                   end;
               end;
             exit;
@@ -226,8 +235,17 @@ uses
         genname:=genname+'$'+countstr;
         ugenname:=upper(genname);
 
-        if not searchsym(ugenname,srsym,st)
-            or (srsym.typ<>typesym) then
+        if assigned(genericdef) and (genericdef.owner.symtabletype in [objectsymtable,recordsymtable]) then
+          begin
+            if genericdef.owner.symtabletype = objectsymtable then
+              found:=searchsym_in_class(tobjectdef(genericdef.owner.defowner),tobjectdef(genericdef.owner.defowner),ugenname,srsym,st,false)
+            else
+              found:=searchsym_in_record(tabstractrecorddef(genericdef.owner.defowner),ugenname,srsym,st);
+          end
+        else
+          found:=searchsym(ugenname,srsym,st);
+
+        if not found or (srsym.typ<>typesym) then
           begin
             identifier_not_found(genname);
             genericdeflist.Free;

+ 29 - 8
compiler/ptype.pas

@@ -168,12 +168,7 @@ implementation
         { handle types inside classes, e.g. TNode.TLongint }
         while (token=_POINT) do
           begin
-            if parse_generic then
-              begin
-                 consume(_POINT);
-                 consume(_ID);
-              end
-             else if is_class_or_object(def) or is_record(def) then
+             if is_class_or_object(def) or is_record(def) then
                begin
                  consume(_POINT);
                  if (structstackindex>=0) and
@@ -373,7 +368,7 @@ implementation
         until not again;
         if ([stoAllowSpecialization,stoAllowTypeDef] * options <> []) and
            (m_delphi in current_settings.modeswitches) then
-          dospecialize:=token=_LSHARPBRACKET;
+          dospecialize:=token in [_LSHARPBRACKET,_LT];
         if dospecialize then
           generate_specialization(def,stoParseClassParent in options,'',nil,'')
         else
@@ -848,7 +843,33 @@ implementation
                    def:=ttypenode(pt1).resultdef;
                    { Delphi mode specialization? }
                    if (m_delphi in current_settings.modeswitches) then
-                     dospecialize:=token=_LSHARPBRACKET;
+                     dospecialize:=token=_LSHARPBRACKET
+                   else
+                     { in non-Delphi modes we might get a inline specialization
+                       without "specialize" or "<T>", so we need to handle that
+                       special }
+                     if not dospecialize and
+                         assigned(ttypenode(pt1).typesym) and
+                         (ttypenode(pt1).typesym.typ=typesym) and
+                         (sp_generic_dummy in ttypenode(pt1).typesym.symoptions) and
+                         assigned(current_structdef) and
+                         (
+                           (
+                             not (m_delphi in current_settings.modeswitches) and
+                             (ttypesym(ttypenode(pt1).typesym).typedef.typ=undefineddef) and
+                             (df_generic in current_structdef.defoptions) and
+                             (upper(ttypenode(pt1).typesym.realname)=copy(current_structdef.objname^,1,pos('$',current_structdef.objname^)-1))
+                           ) or (
+                             (df_specialization in current_structdef.defoptions) and
+                             (ttypesym(ttypenode(pt1).typesym).typedef=current_structdef.genericdef)
+                           )
+                         )
+                         then
+                       begin
+                         def:=current_structdef;
+                         { handle nested types }
+                         post_comp_expr_gendef(def);
+                       end;
                    if dospecialize then
                      begin
                        generate_specialization(def,false,name,nil,'');