Browse Source

generics: store generic type with '<,>' symbols to prevent hiding of regular types with the same name and hiding generics with the same name but different type parameters, search them using '<,>' symbols, in inline specialization do search with look ahead.

git-svn-id: branches/paul/generics@16817 -
paul 14 years ago
parent
commit
5b9adfd0df
47 changed files with 628 additions and 507 deletions
  1. 6 5
      compiler/pbase.pas
  2. 7 3
      compiler/pdecl.pas
  3. 1 1
      compiler/pdecobj.pas
  4. 33 65
      compiler/pdecsub.pas
  5. 7 7
      compiler/pdecvar.pas
  6. 2 2
      compiler/pexports.pas
  7. 216 107
      compiler/pexpr.pas
  8. 5 5
      compiler/pinline.pas
  9. 2 2
      compiler/pp.lpi
  10. 12 12
      compiler/pstatmnt.pas
  11. 13 13
      compiler/ptconst.pas
  12. 73 101
      compiler/ptype.pas
  13. 57 0
      compiler/scanner.pas
  14. 11 1
      compiler/symtable.pas
  15. 121 121
      rtl/objpas/fgl.pp
  16. 4 4
      tests/tbs/ub0569.pp
  17. 1 1
      tests/test/tgeneric1.pp
  18. 2 2
      tests/test/tgeneric11.pp
  19. 2 2
      tests/test/tgeneric12.pp
  20. 2 2
      tests/test/tgeneric15.pp
  21. 3 3
      tests/test/tgeneric16.pp
  22. 3 3
      tests/test/tgeneric17.pp
  23. 1 1
      tests/test/tgeneric19.pp
  24. 1 1
      tests/test/tgeneric2.pp
  25. 1 1
      tests/test/tgeneric20.pp
  26. 9 9
      tests/test/tgeneric22.pp
  27. 1 1
      tests/test/tgeneric5.pp
  28. 1 1
      tests/test/tgeneric6.pp
  29. 3 3
      tests/test/tgeneric8.pp
  30. 1 1
      tests/test/tgeneric9.pp
  31. 2 2
      tests/test/ugeneric10.pp
  32. 1 1
      tests/test/ugeneric14.pp
  33. 1 1
      tests/test/ugeneric3.pp
  34. 1 1
      tests/test/ugeneric4.pp
  35. 1 1
      tests/test/ugeneric7.pp
  36. 6 6
      tests/webtbs/tw10247.pp
  37. 2 2
      tests/webtbs/tw10247b.pp
  38. 1 1
      tests/webtbs/tw11435b.pp
  39. 2 2
      tests/webtbs/tw11435c.pp
  40. 1 1
      tests/webtbs/tw12249.pp
  41. 2 2
      tests/webtbs/tw16065.pp
  42. 1 1
      tests/webtbs/tw17193.pp
  43. 2 2
      tests/webtbs/tw6624.pp
  44. 1 1
      tests/webtbs/tw9673.pp
  45. 1 1
      tests/webtbs/tw9827.pp
  46. 1 1
      tests/webtbs/uw14124.pp
  47. 1 1
      tests/webtbs/uw15591.pp

+ 6 - 5
compiler/pbase.pas

@@ -88,7 +88,7 @@ interface
     function consume_sym(var srsym:tsym;var srsymtable:TSymtable):boolean;
     function consume_sym(var srsym:tsym;var srsymtable:TSymtable):boolean;
     function consume_sym_orgid(var srsym:tsym;var srsymtable:TSymtable;var s : string):boolean;
     function consume_sym_orgid(var srsym:tsym;var srsymtable:TSymtable;var s : string):boolean;
 
 
-    function try_consume_unitsym(var srsym:tsym;var srsymtable:TSymtable;var tokentoconsume : ttoken):boolean;
+    function try_consume_unitsym(var srsym:tsym;var srsymtable:TSymtable;var tokentoconsume:ttoken;const consume_id:boolean):boolean;
 
 
     function try_consume_hintdirective(var symopt:tsymoptions; var deprecatedmsg:pshortstring):boolean;
     function try_consume_hintdirective(var symopt:tsymoptions; var deprecatedmsg:pshortstring):boolean;
 
 
@@ -191,7 +191,7 @@ implementation
           end;
           end;
         searchsym(pattern,srsym,srsymtable);
         searchsym(pattern,srsym,srsymtable);
         { handle unit specification like System.Writeln }
         { handle unit specification like System.Writeln }
-        try_consume_unitsym(srsym,srsymtable,t);
+        try_consume_unitsym(srsym,srsymtable,t,true);
         { if nothing found give error and return errorsym }
         { if nothing found give error and return errorsym }
         if assigned(srsym) then
         if assigned(srsym) then
           check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
           check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
@@ -224,7 +224,7 @@ implementation
           end;
           end;
         searchsym(pattern,srsym,srsymtable);
         searchsym(pattern,srsym,srsymtable);
         { handle unit specification like System.Writeln }
         { handle unit specification like System.Writeln }
-        try_consume_unitsym(srsym,srsymtable,t);
+        try_consume_unitsym(srsym,srsymtable,t,true);
         { if nothing found give error and return errorsym }
         { if nothing found give error and return errorsym }
         if assigned(srsym) then
         if assigned(srsym) then
           check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
           check_hints(srsym,srsym.symoptions,srsym.deprecatedmsg)
@@ -240,7 +240,7 @@ implementation
       end;
       end;
 
 
 
 
-    function try_consume_unitsym(var srsym:tsym;var srsymtable:TSymtable;var tokentoconsume : ttoken):boolean;
+    function try_consume_unitsym(var srsym:tsym;var srsymtable:TSymtable;var tokentoconsume:ttoken;const consume_id:boolean):boolean;
       var
       var
         hmodule: tmodule;
         hmodule: tmodule;
       begin
       begin
@@ -260,7 +260,8 @@ implementation
               internalerror(201001120);
               internalerror(201001120);
             if hmodule.unit_index=current_filepos.moduleindex then
             if hmodule.unit_index=current_filepos.moduleindex then
               begin
               begin
-                consume(_ID);
+                if consume_id then
+                  consume(_ID);
                 consume(_POINT);
                 consume(_POINT);
                 case token of
                 case token of
                   _ID:
                   _ID:

+ 7 - 3
compiler/pdecl.pas

@@ -91,7 +91,7 @@ implementation
         if orgname='' then
         if orgname='' then
          internalerror(9584582);
          internalerror(9584582);
         hp:=nil;
         hp:=nil;
-        p:=comp_expr(true,false);
+        p:=comp_expr(true,[]);
         storetokenpos:=current_tokenpos;
         storetokenpos:=current_tokenpos;
         current_tokenpos:=filepos;
         current_tokenpos:=filepos;
         case p.nodetype of
         case p.nodetype of
@@ -394,7 +394,7 @@ implementation
         end;
         end;
 
 
       var
       var
-         typename,orgtypename : TIDString;
+         typename,orgtypename,tmp : TIDString;
          newtype  : ttypesym;
          newtype  : ttypesym;
          sym      : tsym;
          sym      : tsym;
          srsymtable : TSymtable;
          srsymtable : TSymtable;
@@ -442,6 +442,10 @@ implementation
                consume(_LSHARPBRACKET);
                consume(_LSHARPBRACKET);
                generictypelist:=parse_generic_parameters;
                generictypelist:=parse_generic_parameters;
                consume(_RSHARPBRACKET);
                consume(_RSHARPBRACKET);
+               { modify the type name }
+               tmp:=generate_generic_id_modifier(generictypelist.Count);
+               typename:=typename+tmp;
+               orgtypename:=orgtypename+tmp;
              end;
              end;
 
 
            consume(_EQ);
            consume(_EQ);
@@ -735,7 +739,7 @@ implementation
              _EQ:
              _EQ:
                 begin
                 begin
                    consume(_EQ);
                    consume(_EQ);
-                   p:=comp_expr(true,false);
+                   p:=comp_expr(true,[]);
                    storetokenpos:=current_tokenpos;
                    storetokenpos:=current_tokenpos;
                    current_tokenpos:=filepos;
                    current_tokenpos:=filepos;
                    sym:=nil;
                    sym:=nil;

+ 1 - 1
compiler/pdecobj.pas

@@ -328,7 +328,7 @@ implementation
         p : tnode;
         p : tnode;
         valid : boolean;
         valid : boolean;
       begin
       begin
-        p:=comp_expr(true,false);
+        p:=comp_expr(true,[]);
         if p.nodetype=stringconstn then
         if p.nodetype=stringconstn then
           begin
           begin
             stringdispose(current_objectdef.iidstr);
             stringdispose(current_objectdef.iidstr);

+ 33 - 65
compiler/pdecsub.pas

@@ -902,75 +902,43 @@ implementation
 
 
         function consume_generic_type_parameter:boolean;
         function consume_generic_type_parameter:boolean;
           var
           var
-            i:integer;
-            ok:boolean;
+            typeparamcount:integer;
             sym:tsym;
             sym:tsym;
+            foundname,realname:TIDString;
           begin
           begin
-            result:=not assigned(astruct)and(m_delphi in current_settings.modeswitches);
-            if result then
+            result:=not assigned(astruct);
+            if result and (token=_LT) then
               begin
               begin
-                { a generic type parameter? }
-                srsym:=search_object_name(sp,false);
+                consume(_LT);
+                { a generic type parameter }
+                typeparamcount:=0;
+                foundname:='';
+                repeat
+                  if (token=_ID)  then
+                    begin
+                      inc(typeparamcount);
+                      foundname:=foundname+pattern+',';
+                    end;
+                  consume(_ID);
+                until not try_to_consume(_COMMA);
+                consume(_GT);
+                srsym:=search_object_name(sp+generate_generic_id_modifier(typeparamcount),false);
                 if (srsym.typ=typesym) and
                 if (srsym.typ=typesym) and
                    (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
                    (ttypesym(srsym).typedef.typ in [objectdef,recorddef]) then
-                begin
-                  astruct:=tabstractrecorddef(ttypesym(srsym).typedef);
-                  if (df_generic in astruct.defoptions) and try_to_consume(_LT) then
-                    begin
-                      ok:=true;
-                      i:=0;
-                      repeat
-                        if ok and (token=_ID)  then
-                          begin
-                            ok:=false;
-                            while i<astruct.symtable.SymList.Count-1 do
-                              begin
-                                sym:=tsym(astruct.symtable.SymList[i]);
-                                if sp_generic_para in sym.symoptions then
-                                  begin
-                                    ok:=sym.Name=pattern;
-                                    inc(i);
-                                    break;
-                                  end;
-                                inc(i);
-                              end;
-                            if not ok then
-                              Message1(type_e_generic_declaration_does_not_match,astruct.RttiName);
-                          end;
-                        consume(_ID);
-                      until not try_to_consume(_COMMA);
-                      if ok then
-                        while i<astruct.symtable.SymList.Count-1 do
-                          begin
-                            sym:=tsym(astruct.symtable.SymList[i]);
-                            if sp_generic_para in sym.symoptions then
-                              begin
-                                Message1(type_e_generic_declaration_does_not_match,astruct.RttiName);
-                                break;
-                              end;
-                            inc(i);
-                          end;
-                      consume(_GT);
-                    end
-                  else
-                  if (df_generic in astruct.defoptions) and (token=_POINT) then
-                    begin
+                  begin
+                    astruct:=tabstractrecorddef(ttypesym(srsym).typedef);
+                    realname:='';
+                    for typeparamcount := 0 to astruct.symtable.SymList.Count-1 do
+                      begin
+                        sym:=tsym(astruct.symtable.SymList[typeparamcount]);
+                        if sp_generic_para in sym.symoptions then
+                          realname:=realname+sym.Name+',';
+                      end;
+                    if foundname<>realname then
                       Message1(type_e_generic_declaration_does_not_match,astruct.RttiName);
                       Message1(type_e_generic_declaration_does_not_match,astruct.RttiName);
-                    end
-                  else
-                    begin
-                      { not a method. routine name just accidentally match some structure name }
-                      astruct:=nil;
-                      if try_to_consume(_LT) then
-                        begin
-                          Message(type_e_type_parameters_are_not_allowed_here);
-                          repeat
-                            consume(_ID);
-                          until not try_to_consume(_COMMA);
-                          consume(_GT);
-                        end;
-                    end;
-                end;
+                  end
+                else
+                  Message(type_e_type_parameters_are_not_allowed_here);
               end;
               end;
           end;
           end;
 
 
@@ -1707,7 +1675,7 @@ var pt:Tnode;
 begin
 begin
   if pd.typ<>procdef then
   if pd.typ<>procdef then
     internalerror(200604301);
     internalerror(200604301);
-  pt:=comp_expr(true,false);
+  pt:=comp_expr(true,[]);
   if is_constintnode(pt) then
   if is_constintnode(pt) then
     if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
     if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
       message(parser_e_range_check_error)
       message(parser_e_range_check_error)
@@ -1769,7 +1737,7 @@ begin
       if paracnt<>1 then
       if paracnt<>1 then
         Message(parser_e_ill_msg_param);
         Message(parser_e_ill_msg_param);
     end;
     end;
-  pt:=comp_expr(true,false);
+  pt:=comp_expr(true,[]);
   { message is 1-character long }
   { message is 1-character long }
   if is_constcharnode(pt) then
   if is_constcharnode(pt) then
     begin
     begin

+ 7 - 7
compiler/pdecvar.pas

@@ -177,7 +177,7 @@ implementation
                          if def.typ=arraydef then
                          if def.typ=arraydef then
                           begin
                           begin
                             idx:=0;
                             idx:=0;
-                            p:=comp_expr(true,false);
+                            p:=comp_expr(true,[]);
                             if (not codegenerror) then
                             if (not codegenerror) then
                              begin
                              begin
                                if (p.nodetype=ordconstn) then
                                if (p.nodetype=ordconstn) then
@@ -279,7 +279,7 @@ implementation
 
 
               if try_to_consume(_DISPID) then
               if try_to_consume(_DISPID) then
                 begin
                 begin
-                  pt:=comp_expr(true,false);
+                  pt:=comp_expr(true,[]);
                   if is_constintnode(pt) then
                   if is_constintnode(pt) then
                     if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
                     if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
                       message(parser_e_range_check_error)
                       message(parser_e_range_check_error)
@@ -454,7 +454,7 @@ implementation
               if (idtoken=_INDEX) then
               if (idtoken=_INDEX) then
                 begin
                 begin
                    consume(_INDEX);
                    consume(_INDEX);
-                   pt:=comp_expr(true,false);
+                   pt:=comp_expr(true,[]);
                    { Only allow enum and integer indexes. Convert all integer
                    { Only allow enum and integer indexes. Convert all integer
                      values to s32int to be compatible with delphi, because the
                      values to s32int to be compatible with delphi, because the
                      procedure matching requires equal parameters }
                      procedure matching requires equal parameters }
@@ -723,14 +723,14 @@ implementation
                 begin
                 begin
                   Message(parser_e_property_cant_have_a_default_value);
                   Message(parser_e_property_cant_have_a_default_value);
                   { Error recovery }
                   { Error recovery }
-                  pt:=comp_expr(true,false);
+                  pt:=comp_expr(true,[]);
                   pt.free;
                   pt.free;
                 end
                 end
               else
               else
                 begin
                 begin
                   { Get the result of the default, the firstpass is
                   { Get the result of the default, the firstpass is
                     needed to support values like -1 }
                     needed to support values like -1 }
-                  pt:=comp_expr(true,false);
+                  pt:=comp_expr(true,[]);
                   if (p.propdef.typ=setdef) and
                   if (p.propdef.typ=setdef) and
                      (pt.nodetype=arrayconstructorn) then
                      (pt.nodetype=arrayconstructorn) then
                     begin
                     begin
@@ -1674,11 +1674,11 @@ implementation
               symtablestack.push(UnionSymtable);
               symtablestack.push(UnionSymtable);
               repeat
               repeat
                 repeat
                 repeat
-                  pt:=comp_expr(true,false);
+                  pt:=comp_expr(true,[]);
                   if not(pt.nodetype=ordconstn) then
                   if not(pt.nodetype=ordconstn) then
                     Message(parser_e_illegal_expression);
                     Message(parser_e_illegal_expression);
                   if try_to_consume(_POINTPOINT) then
                   if try_to_consume(_POINTPOINT) then
-                    pt:=crangenode.create(pt,comp_expr(true,false));
+                    pt:=crangenode.create(pt,comp_expr(true,[]));
                   pt.free;
                   pt.free;
                   if token=_COMMA then
                   if token=_COMMA then
                     consume(_COMMA)
                     consume(_COMMA)

+ 2 - 2
compiler/pexports.pas

@@ -136,7 +136,7 @@ implementation
                      end;
                      end;
                     if try_to_consume(_INDEX) then
                     if try_to_consume(_INDEX) then
                      begin
                      begin
-                       pt:=comp_expr(true,false);
+                       pt:=comp_expr(true,[]);
                        if pt.nodetype=ordconstn then
                        if pt.nodetype=ordconstn then
                         if (Tordconstnode(pt).value<int64(low(index))) or
                         if (Tordconstnode(pt).value<int64(low(index))) or
                            (Tordconstnode(pt).value>int64(high(index))) then
                            (Tordconstnode(pt).value>int64(high(index))) then
@@ -160,7 +160,7 @@ implementation
                      end;
                      end;
                     if try_to_consume(_NAME) then
                     if try_to_consume(_NAME) then
                      begin
                      begin
-                       pt:=comp_expr(true,false);
+                       pt:=comp_expr(true,[]);
                        if pt.nodetype=stringconstn then
                        if pt.nodetype=stringconstn then
                          hpname:=strpas(tstringconstnode(pt).value_str)
                          hpname:=strpas(tstringconstnode(pt).value_str)
                        else
                        else

+ 216 - 107
compiler/pexpr.pas

@@ -30,14 +30,21 @@ interface
       node,ncal,
       node,ncal,
       tokens,globtype,globals,constexp;
       tokens,globtype,globals,constexp;
 
 
+    type
+      TExprOption=(
+        eoTypeOnly,    { search only type names }
+        eoSpecialize   { do specialization      }
+      );
+      TExprOptions = set of TExprOption;
+
     { reads a whole expression }
     { reads a whole expression }
     function expr(dotypecheck:boolean) : tnode;
     function expr(dotypecheck:boolean) : tnode;
 
 
     { reads an expression without assignements and .. }
     { reads an expression without assignements and .. }
-    function comp_expr(accept_equal,typeonly:boolean):tnode;
+    function comp_expr(accept_equal:boolean;options:TExprOptions):tnode;
 
 
     { reads a single factor }
     { reads a single factor }
-    function factor(getaddr,typeonly:boolean) : tnode;
+    function factor(getaddr:boolean;options:TExprOptions) : tnode;
 
 
     procedure string_dec(var def: tdef; allowtypedef: boolean);
     procedure string_dec(var def: tdef; allowtypedef: boolean);
 
 
@@ -53,7 +60,7 @@ implementation
 
 
     uses
     uses
        { common }
        { common }
-       cutils,
+       cutils,cclasses,
        { global }
        { global }
        verbose,
        verbose,
        systems,widestr,
        systems,widestr,
@@ -79,7 +86,7 @@ implementation
     const
     const
       highest_precedence = oppower;
       highest_precedence = oppower;
 
 
-    function sub_expr(pred_level:Toperator_precedence;accept_equal,typeonly:boolean):tnode;forward;
+    function sub_expr(pred_level:Toperator_precedence;accept_equal:boolean;options:TExprOptions):tnode;forward;
 
 
     const
     const
        { true, if the inherited call is anonymous }
        { true, if the inherited call is anonymous }
@@ -101,7 +108,7 @@ implementation
               if not(allowtypedef) then
               if not(allowtypedef) then
                 Message(parser_e_no_local_para_def);
                 Message(parser_e_no_local_para_def);
               consume(_LECKKLAMMER);
               consume(_LECKKLAMMER);
-              p:=comp_expr(true,false);
+              p:=comp_expr(true,[]);
               if not is_constintnode(p) then
               if not is_constintnode(p) then
                 begin
                 begin
                   Message(parser_e_illegal_expression);
                   Message(parser_e_illegal_expression);
@@ -172,12 +179,12 @@ implementation
                else
                else
                  begin
                  begin
                    named_args_allowed:=true;
                    named_args_allowed:=true;
-                   p1:=comp_expr(true,false);
+                   p1:=comp_expr(true,[]);
                    named_args_allowed:=false;
                    named_args_allowed:=false;
                    if found_arg_name then
                    if found_arg_name then
                      begin
                      begin
                        argname:=p1;
                        argname:=p1;
-                       p1:=comp_expr(true,false);
+                       p1:=comp_expr(true,[]);
                        p2:=ccallparanode.create(p1,p2);
                        p2:=ccallparanode.create(p1,p2);
                        tcallparanode(p2).parametername:=argname;
                        tcallparanode(p2).parametername:=argname;
                      end
                      end
@@ -188,19 +195,19 @@ implementation
              end
              end
            else
            else
              begin
              begin
-               p1:=comp_expr(true,false);
+               p1:=comp_expr(true,[]);
                p2:=ccallparanode.create(p1,p2);
                p2:=ccallparanode.create(p1,p2);
              end;
              end;
            { it's for the str(l:5,s); }
            { it's for the str(l:5,s); }
            if __colon and (token=_COLON) then
            if __colon and (token=_COLON) then
              begin
              begin
                consume(_COLON);
                consume(_COLON);
-               p1:=comp_expr(true,false);
+               p1:=comp_expr(true,[]);
                p2:=ccallparanode.create(p1,p2);
                p2:=ccallparanode.create(p1,p2);
                include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
                include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
                if try_to_consume(_COLON) then
                if try_to_consume(_COLON) then
                  begin
                  begin
-                   p1:=comp_expr(true,false);
+                   p1:=comp_expr(true,[]);
                    p2:=ccallparanode.create(p1,p2);
                    p2:=ccallparanode.create(p1,p2);
                    include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
                    include(tcallparanode(p2).callparaflags,cpf_is_colon_para);
                  end
                  end
@@ -282,7 +289,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               p1:=geninlinenode(in_ord_x,false,p1);
               p1:=geninlinenode(in_ord_x,false,p1);
               statement_syssym := p1;
               statement_syssym := p1;
@@ -296,7 +303,7 @@ implementation
                     begin
                     begin
                       if not(try_to_consume(_RKLAMMER)) then
                       if not(try_to_consume(_RKLAMMER)) then
                         begin
                         begin
-                          p1:=comp_expr(true,false);
+                          p1:=comp_expr(true,[]);
                           consume(_RKLAMMER);
                           consume(_RKLAMMER);
                           if (not assigned(current_procinfo) or
                           if (not assigned(current_procinfo) or
                               is_void(current_procinfo.procdef.returndef)) then
                               is_void(current_procinfo.procdef.returndef)) then
@@ -360,7 +367,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               if p1.nodetype=typen then
               if p1.nodetype=typen then
                 ttypenode(p1).allowed:=true;
                 ttypenode(p1).allowed:=true;
@@ -386,7 +393,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               if (p1.nodetype<>typen) and
               if (p1.nodetype<>typen) and
                  (
                  (
@@ -431,7 +438,7 @@ implementation
                 begin
                 begin
                   consume(_LKLAMMER);
                   consume(_LKLAMMER);
                   in_args:=true;
                   in_args:=true;
-                  p1:=comp_expr(true,false);
+                  p1:=comp_expr(true,[]);
                   { When reading a class type it is parsed as loadvmtaddrn,
                   { When reading a class type it is parsed as loadvmtaddrn,
                     typeinfo only needs the type so we remove the loadvmtaddrn }
                     typeinfo only needs the type so we remove the loadvmtaddrn }
                   if p1.nodetype=loadvmtaddrn then
                   if p1.nodetype=loadvmtaddrn then
@@ -465,7 +472,7 @@ implementation
               err:=false;
               err:=false;
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p2:=ccallparanode.create(p1,nil);
               p2:=ccallparanode.create(p1,nil);
               p2:=geninlinenode(in_unaligned_x,false,p2);
               p2:=geninlinenode(in_unaligned_x,false,p2);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
@@ -477,7 +484,7 @@ implementation
               err:=false;
               err:=false;
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               { When reading a class type it is parsed as loadvmtaddrn,
               { When reading a class type it is parsed as loadvmtaddrn,
                 typeinfo only needs the type so we remove the loadvmtaddrn }
                 typeinfo only needs the type so we remove the loadvmtaddrn }
               if p1.nodetype=loadvmtaddrn then
               if p1.nodetype=loadvmtaddrn then
@@ -533,7 +540,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p1:=caddrnode.create(p1);
               p1:=caddrnode.create(p1);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               statement_syssym:=p1;
               statement_syssym:=p1;
@@ -543,7 +550,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p1:=caddrnode.create(p1);
               p1:=caddrnode.create(p1);
               do_typecheckpass(p1);
               do_typecheckpass(p1);
               { Ofs() returns a cardinal/qword, not a pointer }
               { Ofs() returns a cardinal/qword, not a pointer }
@@ -556,7 +563,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p1:=geninlinenode(in_seg_x,false,p1);
               p1:=geninlinenode(in_seg_x,false,p1);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               statement_syssym:=p1;
               statement_syssym:=p1;
@@ -567,7 +574,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p2:=geninlinenode(l,false,p1);
               p2:=geninlinenode(l,false,p1);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               statement_syssym:=p2;
               statement_syssym:=p2;
@@ -578,7 +585,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p2:=geninlinenode(l,false,p1);
               p2:=geninlinenode(l,false,p1);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               statement_syssym:=p2;
               statement_syssym:=p2;
@@ -589,9 +596,9 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               if try_to_consume(_COMMA) then
               if try_to_consume(_COMMA) then
-                p2:=ccallparanode.create(comp_expr(true,false),nil)
+                p2:=ccallparanode.create(comp_expr(true,[]),nil)
               else
               else
                 p2:=nil;
                 p2:=nil;
               p2:=ccallparanode.create(p1,p2);
               p2:=ccallparanode.create(p1,p2);
@@ -606,9 +613,9 @@ implementation
                   message(parser_e_illegal_slice);
                   message(parser_e_illegal_slice);
                   consume(_LKLAMMER);
                   consume(_LKLAMMER);
                   in_args:=true;
                   in_args:=true;
-                  comp_expr(true,false).free;
+                  comp_expr(true,[]).free;
                   if try_to_consume(_COMMA) then
                   if try_to_consume(_COMMA) then
-                    comp_expr(true,false).free;
+                    comp_expr(true,[]).free;
                   statement_syssym:=cerrornode.create;
                   statement_syssym:=cerrornode.create;
                   consume(_RKLAMMER);
                   consume(_RKLAMMER);
                 end
                 end
@@ -616,10 +623,10 @@ implementation
                 begin
                 begin
                   consume(_LKLAMMER);
                   consume(_LKLAMMER);
                   in_args:=true;
                   in_args:=true;
-                  p1:=comp_expr(true,false);
+                  p1:=comp_expr(true,[]);
                   Consume(_COMMA);
                   Consume(_COMMA);
                   if not(codegenerror) then
                   if not(codegenerror) then
-                    p2:=ccallparanode.create(comp_expr(true,false),nil)
+                    p2:=ccallparanode.create(comp_expr(true,[]),nil)
                   else
                   else
                     p2:=cerrornode.create;
                     p2:=cerrornode.create;
                   p2:=ccallparanode.create(p1,p2);
                   p2:=ccallparanode.create(p1,p2);
@@ -651,7 +658,7 @@ implementation
                 type checking }
                 type checking }
               p2:=nil;
               p2:=nil;
               repeat
               repeat
-                p1:=comp_expr(true,false);
+                p1:=comp_expr(true,[]);
                 if p2<>nil then
                 if p2<>nil then
                   p2:=caddnode.create(addn,p2,p1)
                   p2:=caddnode.create(addn,p2,p1)
                 else
                 else
@@ -697,7 +704,7 @@ implementation
                   consume(_LKLAMMER);
                   consume(_LKLAMMER);
                   in_args:=true;
                   in_args:=true;
                   { don't turn procsyms into calls (getaddr = true) }
                   { don't turn procsyms into calls (getaddr = true) }
-                  p1:=factor(true,false);
+                  p1:=factor(true,[]);
                   p2:=geninlinenode(l,false,p1);
                   p2:=geninlinenode(l,false,p1);
                   consume(_RKLAMMER);
                   consume(_RKLAMMER);
                   statement_syssym:=p2;
                   statement_syssym:=p2;
@@ -712,7 +719,7 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               p2:=geninlinenode(l,false,p1);
               p2:=geninlinenode(l,false,p1);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               statement_syssym:=p2;
               statement_syssym:=p2;
@@ -746,11 +753,11 @@ implementation
             Begin
             Begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args := true;
               in_args := true;
-              p1:= ccallparanode.create(comp_expr(true,false), nil);
+              p1:= ccallparanode.create(comp_expr(true,[]), nil);
               consume(_COMMA);
               consume(_COMMA);
-              p2 := ccallparanode.create(comp_expr(true,false),p1);
+              p2 := ccallparanode.create(comp_expr(true,[]),p1);
               if try_to_consume(_COMMA) then
               if try_to_consume(_COMMA) then
-                p2 := ccallparanode.create(comp_expr(true,false),p2);
+                p2 := ccallparanode.create(comp_expr(true,[]),p2);
               consume(_RKLAMMER);
               consume(_RKLAMMER);
               p2 := geninlinenode(l,false,p2);
               p2 := geninlinenode(l,false,p2);
               statement_syssym := p2;
               statement_syssym := p2;
@@ -761,9 +768,9 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               consume(_COMMA);
               consume(_COMMA);
-              p2:=comp_expr(true,false);
+              p2:=comp_expr(true,[]);
               statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
               statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,nil)));
               consume(_RKLAMMER);
               consume(_RKLAMMER);
             end;
             end;
@@ -773,11 +780,11 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               consume(_COMMA);
               consume(_COMMA);
-              p2:=comp_expr(true,false);
+              p2:=comp_expr(true,[]);
               consume(_COMMA);
               consume(_COMMA);
-              paras:=comp_expr(true,false);
+              paras:=comp_expr(true,[]);
               statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,ccallparanode.create(paras,nil))));
               statement_syssym:=geninlinenode(l,false,ccallparanode.create(p1,ccallparanode.create(p2,ccallparanode.create(paras,nil))));
               consume(_RKLAMMER);
               consume(_RKLAMMER);
             end;
             end;
@@ -786,9 +793,9 @@ implementation
             begin
             begin
               consume(_LKLAMMER);
               consume(_LKLAMMER);
               in_args:=true;
               in_args:=true;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               if try_to_consume(_COMMA) then
               if try_to_consume(_COMMA) then
-                 p2:=comp_expr(true,false)
+                 p2:=comp_expr(true,[])
               else
               else
                begin
                begin
                  { then insert an empty string }
                  { then insert an empty string }
@@ -1093,7 +1100,7 @@ implementation
                          { read the expression }
                          { read the expression }
                          if propsym.propdef.typ=procvardef then
                          if propsym.propdef.typ=procvardef then
                            getprocvardef:=tprocvardef(propsym.propdef);
                            getprocvardef:=tprocvardef(propsym.propdef);
-                         p2:=comp_expr(true,false);
+                         p2:=comp_expr(true,[]);
                          if assigned(getprocvardef) then
                          if assigned(getprocvardef) then
                            handle_procvar(getprocvardef,p2);
                            handle_procvar(getprocvardef,p2);
                          tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
                          tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left);
@@ -1109,7 +1116,7 @@ implementation
                          include(p1.flags,nf_isproperty);
                          include(p1.flags,nf_isproperty);
                          consume(_ASSIGNMENT);
                          consume(_ASSIGNMENT);
                          { read the expression }
                          { read the expression }
-                         p2:=comp_expr(true,false);
+                         p2:=comp_expr(true,[]);
                          p1:=cassignmentnode.create(p1,p2);
                          p1:=cassignmentnode.create(p1,p2);
                       end
                       end
                     else
                     else
@@ -1121,8 +1128,8 @@ implementation
                 end
                 end
               else
               else
                 begin
                 begin
-                   p1:=cerrornode.create;
-                   Message(parser_e_no_procedure_to_access_property);
+                  p1:=cerrornode.create;
+                  Message(parser_e_no_procedure_to_access_property);
                 end;
                 end;
            end
            end
          else
          else
@@ -1240,7 +1247,7 @@ implementation
                      p1.free;
                      p1.free;
                      if try_to_consume(_LKLAMMER) then
                      if try_to_consume(_LKLAMMER) then
                       begin
                       begin
-                        p1:=comp_expr(true,false);
+                        p1:=comp_expr(true,[]);
                         consume(_RKLAMMER);
                         consume(_RKLAMMER);
                         p1:=ctypeconvnode.create_explicit(p1,ttypesym(sym).typedef);
                         p1:=ctypeconvnode.create_explicit(p1,ttypesym(sym).typedef);
                       end
                       end
@@ -1318,9 +1325,43 @@ implementation
         end;
         end;
       end;
       end;
 
 
+    function get_generic_id_modifier:TIDString;
+      var
+        savedstate:tscannerstate;
+        typeparamcount:integer;
+      begin
+        { this functions test the token stream that it contains a valid
+          <TypeParam1, TypeParam2> sequence and if it so it returns that
+          sequence mask like <,> for the given example. if the sequence
+          is not valid the return value is an empty string }
+        result:='';
+        { to safely search the token stream we need to save it state and restore
+          it later }
+        savedstate:=current_scanner.savestate;
+        try
+          { sequnce must start with '<' symbol which under different conditions
+            maps either to _LSHARPBRACKET or to _LT token }
+          if not (try_to_consume(_LSHARPBRACKET) or try_to_consume(_LT)) then
+            exit;
+          typeparamcount:=0;
+          repeat
+            inc(typeparamcount);
+            { stop sequnce search if token is suspicious }
+            while not (token in ([_RSHARPBRACKET,_GT,_COMMA,_EOF] + endtokens)) do
+              consume(token);
+          until not try_to_consume(_COMMA);
+          { sequnce must finish with '>' symbol wich similar maps to 2 tokens }
+          if not (try_to_consume(_RSHARPBRACKET) or try_to_consume(_GT)) then
+            exit;
+          result:=generate_generic_id_modifier(typeparamcount);
+        finally
+          current_scanner.restorestate(savedstate);
+        end;
+      end;
+
   {$maxfpuregisters 0}
   {$maxfpuregisters 0}
 
 
-    function factor(getaddr,typeonly:boolean) : tnode;
+    function factor(getaddr:boolean;options:TExprOptions) : tnode;
 
 
          {---------------------------------------------
          {---------------------------------------------
                          Factor_read_id
                          Factor_read_id
@@ -1332,13 +1373,16 @@ implementation
            srsymtable : TSymtable;
            srsymtable : TSymtable;
            hdef  : tdef;
            hdef  : tdef;
            orgstoredpattern,
            orgstoredpattern,
-           storedpattern : string;
+           storedpattern, generic_id_modifier : string;
            callflags: tcallnodeflags;
            callflags: tcallnodeflags;
            t : ttoken;
            t : ttoken;
            unit_found : boolean;
            unit_found : boolean;
+           structdef : tabstractrecorddef;
+           typeparams: TFPObjectList;
          begin
          begin
            { allow post fix operators }
            { allow post fix operators }
            again:=true;
            again:=true;
+           typeparams:=nil;
 
 
            { first check for identifier }
            { first check for identifier }
            if token<>_ID then
            if token<>_ID then
@@ -1349,17 +1393,65 @@ implementation
              end
              end
            else
            else
              begin
              begin
-               if typeonly then
-                 searchsym_type(pattern,srsym,srsymtable)
-               else
-                 searchsym(pattern,srsym,srsymtable);
-
-               { handle unit specification like System.Writeln }
-               unit_found:=try_consume_unitsym(srsym,srsymtable,t);
                storedpattern:=pattern;
                storedpattern:=pattern;
                orgstoredpattern:=orgpattern;
                orgstoredpattern:=orgpattern;
-               consume(t);
+               consume(_ID);
+               if eoTypeOnly in options then
+                 begin
+                   { searching a generic }
+                   if (eoSpecialize in options) or
+                      ((m_delphi in current_settings.modeswitches) and  (token=_LSHARPBRACKET)) then
+                     begin
+                       typeparams:=TFPObjectList.Create(true);
+                       consume(_LSHARPBRACKET);
+                       repeat
+                         typeparams.add(factor(false,[eoTypeOnly]));
+                       until not try_to_consume(_COMMA);
+                       consume(_RSHARPBRACKET);
+                       generic_id_modifier:=generate_generic_id_modifier(typeparams.count);
+                       { modify patterns }
+                       storedpattern:=storedpattern+generic_id_modifier;
+                       orgstoredpattern:=orgstoredpattern+generic_id_modifier;
+                     end;
+                   searchsym_type(storedpattern,srsym,srsymtable);
+                 end
+               else
+                 begin
+                   srsym:=nil;
+                   { this can be a generic }
+                   if (eoSpecialize in options) or
+                      ((token=_LT) and (m_delphi in current_settings.modeswitches)) then
+                     begin
+                       generic_id_modifier:=get_generic_id_modifier;
+                       if generic_id_modifier<>'' then
+                         begin
+                           searchsym(storedpattern+generic_id_modifier,srsym,srsymtable);
+                           if assigned(srsym) then
+                             begin
+                               typeparams:=TFPObjectList.Create(true);
+                               consume(_LT);
+                               repeat
+                                 typeparams.add(factor(false,[eoTypeOnly]));
+                               until not try_to_consume(_COMMA);
+                               consume(_GT);
+                               { modify patterns }
+                               storedpattern:=storedpattern+generic_id_modifier;
+                               orgstoredpattern:=orgstoredpattern+generic_id_modifier;
+                             end;
+                         end;
+                     end;
+                   if not assigned(srsym) then
+                     searchsym(storedpattern,srsym,srsymtable);
+                 end;
 
 
+               { handle unit specification like System.Writeln }
+               unit_found:=try_consume_unitsym(srsym,srsymtable,t,false);
+               if unit_found then
+                 begin
+                   storedpattern:=pattern;
+                   orgstoredpattern:=orgpattern;
+                   consume(t);
+                 end;
                { named parameter support }
                { named parameter support }
                found_arg_name:=false;
                found_arg_name:=false;
 
 
@@ -1370,6 +1462,7 @@ implementation
                     found_arg_name:=true;
                     found_arg_name:=true;
                     p1:=cstringconstnode.createstr(storedpattern);
                     p1:=cstringconstnode.createstr(storedpattern);
                     consume(_ASSIGNMENT);
                     consume(_ASSIGNMENT);
+                    typeparams.free;
                     exit;
                     exit;
                   end;
                   end;
                { if nothing found give error and return errorsym }
                { if nothing found give error and return errorsym }
@@ -1475,18 +1568,33 @@ implementation
                      end
                      end
                     else
                     else
                      begin
                      begin
+                       if hdef.typ=errordef then
+                         begin
+                           structdef:=current_structdef;
+                           while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
+                             begin
+                               if (structdef.objname^=storedpattern) then
+                                 begin
+                                   hdef:=structdef;
+                                   if assigned(typeparams) then
+                                     generate_specialization(hdef,typeparams,false);
+                                   p1:=ctypenode.create(hdef);
+                                   typeparams.free;
+                                   exit;
+                                 end;
+                               structdef:=tabstractrecorddef(structdef.owner.defowner);
+                             end;
+                         end;
                        { We need to know if this unit uses Variants }
                        { We need to know if this unit uses Variants }
                        if (hdef=cvarianttype) and
                        if (hdef=cvarianttype) and
                           not(cs_compilesystem in current_settings.moduleswitches) then
                           not(cs_compilesystem in current_settings.moduleswitches) then
                          current_module.flags:=current_module.flags or uf_uses_variants;
                          current_module.flags:=current_module.flags or uf_uses_variants;
                        { if we get a generic then check that it is not an inline specialization }
                        { if we get a generic then check that it is not an inline specialization }
-                       if (df_generic in hdef.defoptions) and
-                          (token=_LT) and
-                          (m_delphi in current_settings.modeswitches) then
-                          generate_specialization(hdef,false);
+                       if assigned(typeparams) then
+                          generate_specialization(hdef,typeparams,false);
                        if try_to_consume(_LKLAMMER) then
                        if try_to_consume(_LKLAMMER) then
                         begin
                         begin
-                          p1:=comp_expr(true,false);
+                          p1:=comp_expr(true,[]);
                           consume(_RKLAMMER);
                           consume(_RKLAMMER);
                           p1:=ctypeconvnode.create_explicit(p1,hdef);
                           p1:=ctypeconvnode.create_explicit(p1,hdef);
                         end
                         end
@@ -1687,6 +1795,7 @@ implementation
                   end;
                   end;
               end; { end case }
               end; { end case }
             end;
             end;
+            typeparams.free;
          end;
          end;
 
 
          {---------------------------------------------
          {---------------------------------------------
@@ -1711,10 +1820,10 @@ implementation
               { nested array constructors are not allowed, see also tests/webtbs/tw17213.pp }
               { nested array constructors are not allowed, see also tests/webtbs/tw17213.pp }
               old_allow_array_constructor:=allow_array_constructor;
               old_allow_array_constructor:=allow_array_constructor;
               allow_array_constructor:=false;
               allow_array_constructor:=false;
-              p1:=comp_expr(true,false);
+              p1:=comp_expr(true,[]);
               if try_to_consume(_POINTPOINT) then
               if try_to_consume(_POINTPOINT) then
                 begin
                 begin
-                  p2:=comp_expr(true,false);
+                  p2:=comp_expr(true,[]);
                   p1:=carrayconstructorrangenode.create(p1,p2);
                   p1:=carrayconstructorrangenode.create(p1,p2);
                 end;
                 end;
                { insert at the end of the tree, to get the correct order }
                { insert at the end of the tree, to get the correct order }
@@ -1752,14 +1861,14 @@ implementation
                 else if try_to_consume(_LECKKLAMMER) then
                 else if try_to_consume(_LECKKLAMMER) then
                   begin
                   begin
                     repeat
                     repeat
-                      comp_expr(true,false);
+                      comp_expr(true,[]);
                     until not try_to_consume(_COMMA);
                     until not try_to_consume(_COMMA);
                     consume(_RECKKLAMMER);
                     consume(_RECKKLAMMER);
                   end
                   end
                 else if try_to_consume(_LKLAMMER) then
                 else if try_to_consume(_LKLAMMER) then
                   begin
                   begin
                     repeat
                     repeat
-                      comp_expr(true,false);
+                      comp_expr(true,[]);
                     until not try_to_consume(_COMMA);
                     until not try_to_consume(_COMMA);
                     consume(_RKLAMMER);
                     consume(_RKLAMMER);
                   end
                   end
@@ -1790,7 +1899,7 @@ implementation
 
 
             countindices:=0;
             countindices:=0;
             repeat
             repeat
-              p4:=comp_expr(true,false);
+              p4:=comp_expr(true,[]);
 
 
               addstatement(newstatement,cassignmentnode.create(
               addstatement(newstatement,cassignmentnode.create(
                 ctemprefnode.create_offset(temp,countindices*s32inttype.size),p4));
                 ctemprefnode.create_offset(temp,countindices*s32inttype.size),p4));
@@ -1806,7 +1915,7 @@ implementation
             if token=_ASSIGNMENT then
             if token=_ASSIGNMENT then
               begin
               begin
                 consume(_ASSIGNMENT);
                 consume(_ASSIGNMENT);
-                p4:=comp_expr(true,false);
+                p4:=comp_expr(true,[]);
 
 
                 { create call to fpc_vararray_put }
                 { create call to fpc_vararray_put }
                 paras:=ccallparanode.create(cordconstnode.create
                 paras:=ccallparanode.create(cordconstnode.create
@@ -1937,10 +2046,10 @@ implementation
                                  if (tpointerdef(p1.resultdef).pointeddef.typ=arraydef) and
                                  if (tpointerdef(p1.resultdef).pointeddef.typ=arraydef) and
                                     (m_autoderef in current_settings.modeswitches) then
                                     (m_autoderef in current_settings.modeswitches) then
                                    p1:=cderefnode.create(p1);
                                    p1:=cderefnode.create(p1);
-                                 p2:=comp_expr(true,false);
+                                 p2:=comp_expr(true,[]);
                                  { Support Pbytevar[0..9] which returns array [0..9].}
                                  { Support Pbytevar[0..9] which returns array [0..9].}
                                  if try_to_consume(_POINTPOINT) then
                                  if try_to_consume(_POINTPOINT) then
-                                   p2:=crangenode.create(p2,comp_expr(true,false));
+                                   p2:=crangenode.create(p2,comp_expr(true,[]));
                                  p1:=cvecnode.create(p1,p2);
                                  p1:=cvecnode.create(p1,p2);
                               end;
                               end;
                             variantdef:
                             variantdef:
@@ -1951,15 +2060,15 @@ implementation
                               end;
                               end;
                             stringdef :
                             stringdef :
                               begin
                               begin
-                                p2:=comp_expr(true,false);
+                                p2:=comp_expr(true,[]);
                                 { Support string[0..9] which returns array [0..9] of char.}
                                 { Support string[0..9] which returns array [0..9] of char.}
                                 if try_to_consume(_POINTPOINT) then
                                 if try_to_consume(_POINTPOINT) then
-                                  p2:=crangenode.create(p2,comp_expr(true,false));
+                                  p2:=crangenode.create(p2,comp_expr(true,[]));
                                 p1:=cvecnode.create(p1,p2);
                                 p1:=cvecnode.create(p1,p2);
                               end;
                               end;
                             arraydef:
                             arraydef:
                               begin
                               begin
-                                p2:=comp_expr(true,false);
+                                p2:=comp_expr(true,[]);
                                 { support SEG:OFS for go32v2 Mem[] }
                                 { support SEG:OFS for go32v2 Mem[] }
                                 if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
                                 if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
                                    (p1.nodetype=loadn) and
                                    (p1.nodetype=loadn) and
@@ -1973,11 +2082,11 @@ implementation
                                     if try_to_consume(_COLON) then
                                     if try_to_consume(_COLON) then
                                      begin
                                      begin
                                        p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2);
                                        p3:=caddnode.create(muln,cordconstnode.create($10,s32inttype,false),p2);
-                                       p2:=comp_expr(true,false);
+                                       p2:=comp_expr(true,[]);
                                        p2:=caddnode.create(addn,p2,p3);
                                        p2:=caddnode.create(addn,p2,p3);
                                        if try_to_consume(_POINTPOINT) then
                                        if try_to_consume(_POINTPOINT) then
                                          { Support mem[$a000:$0000..$07ff] which returns array [0..$7ff] of memtype.}
                                          { Support mem[$a000:$0000..$07ff] which returns array [0..$7ff] of memtype.}
-                                         p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true,false),p3.getcopy));
+                                         p2:=crangenode.create(p2,caddnode.create(addn,comp_expr(true,[]),p3.getcopy));
                                        p1:=cvecnode.create(p1,p2);
                                        p1:=cvecnode.create(p1,p2);
                                        include(tvecnode(p1).flags,nf_memseg);
                                        include(tvecnode(p1).flags,nf_memseg);
                                        include(tvecnode(p1).flags,nf_memindex);
                                        include(tvecnode(p1).flags,nf_memindex);
@@ -1986,7 +2095,7 @@ implementation
                                      begin
                                      begin
                                        if try_to_consume(_POINTPOINT) then
                                        if try_to_consume(_POINTPOINT) then
                                          { Support mem[$80000000..$80000002] which returns array [0..2] of memtype.}
                                          { Support mem[$80000000..$80000002] which returns array [0..2] of memtype.}
-                                         p2:=crangenode.create(p2,comp_expr(true,false));
+                                         p2:=crangenode.create(p2,comp_expr(true,[]));
                                        p1:=cvecnode.create(p1,p2);
                                        p1:=cvecnode.create(p1,p2);
                                        include(tvecnode(p1).flags,nf_memindex);
                                        include(tvecnode(p1).flags,nf_memindex);
                                      end;
                                      end;
@@ -1995,7 +2104,7 @@ implementation
                                   begin
                                   begin
                                     if try_to_consume(_POINTPOINT) then
                                     if try_to_consume(_POINTPOINT) then
                                       { Support arrayvar[0..9] which returns array [0..9] of arraytype.}
                                       { Support arrayvar[0..9] which returns array [0..9] of arraytype.}
-                                      p2:=crangenode.create(p2,comp_expr(true,false));
+                                      p2:=crangenode.create(p2,comp_expr(true,[]));
                                     p1:=cvecnode.create(p1,p2);
                                     p1:=cvecnode.create(p1,p2);
                                   end;
                                   end;
                               end;
                               end;
@@ -2005,7 +2114,7 @@ implementation
                                   Message(parser_e_invalid_qualifier);
                                   Message(parser_e_invalid_qualifier);
                                 p1.destroy;
                                 p1.destroy;
                                 p1:=cerrornode.create;
                                 p1:=cerrornode.create;
-                                comp_expr(true,false);
+                                comp_expr(true,[]);
                                 again:=false;
                                 again:=false;
                               end;
                               end;
                           end;
                           end;
@@ -2096,7 +2205,7 @@ implementation
                                  begin
                                  begin
                                    consume(_ASSIGNMENT);
                                    consume(_ASSIGNMENT);
                                    { read the expression }
                                    { read the expression }
-                                   p3:=comp_expr(true,false);
+                                   p3:=comp_expr(true,[]);
                                    { concat value parameter too }
                                    { concat value parameter too }
                                    p2:=ccallparanode.create(p3,p2);
                                    p2:=ccallparanode.create(p3,p2);
                                    p1:=translate_disp_call(p1,p2,dct_propput,dispatchstring,0,voidtype);
                                    p1:=translate_disp_call(p1,p2,dct_propput,dispatchstring,0,voidtype);
@@ -2216,7 +2325,7 @@ implementation
                          begin
                          begin
                            if try_to_consume(_LKLAMMER) then
                            if try_to_consume(_LKLAMMER) then
                              begin
                              begin
-                               p1:=comp_expr(true,false);
+                               p1:=comp_expr(true,[]);
                                consume(_RKLAMMER);
                                consume(_RKLAMMER);
                                p1:=ctypeconvnode.create_explicit(p1,p1.resultdef);
                                p1:=ctypeconvnode.create_explicit(p1,p1.resultdef);
                              end
                              end
@@ -2277,7 +2386,7 @@ implementation
          filepos    : tfileposinfo;
          filepos    : tfileposinfo;
          again,
          again,
          updatefpos,
          updatefpos,
-         nodechanged  : boolean;
+         nodechanged : boolean;
       begin
       begin
         { can't keep a copy of p1 and compare pointers afterwards, because
         { can't keep a copy of p1 and compare pointers afterwards, because
           p1 may be freed and reallocated in the same place!  }
           p1 may be freed and reallocated in the same place!  }
@@ -2319,7 +2428,7 @@ implementation
                 begin
                 begin
                   consume(_RETURN);
                   consume(_RETURN);
                   if not(token in [_SEMICOLON,_ELSE,_END]) then
                   if not(token in [_SEMICOLON,_ELSE,_END]) then
-                    p1 := cexitnode.create(comp_expr(true,false))
+                    p1 := cexitnode.create(comp_expr(true,[]))
                   else
                   else
                     p1 := cexitnode.create(nil);
                     p1 := cexitnode.create(nil);
                 end;
                 end;
@@ -2506,7 +2615,7 @@ implementation
                  { STRING can be also a type cast }
                  { STRING can be also a type cast }
                  if try_to_consume(_LKLAMMER) then
                  if try_to_consume(_LKLAMMER) then
                   begin
                   begin
-                    p1:=comp_expr(true,false);
+                    p1:=comp_expr(true,[]);
                     consume(_RKLAMMER);
                     consume(_RKLAMMER);
                     p1:=ctypeconvnode.create_explicit(p1,hdef);
                     p1:=ctypeconvnode.create_explicit(p1,hdef);
                     { handle postfix operators here e.g. string(a)[10] }
                     { handle postfix operators here e.g. string(a)[10] }
@@ -2524,7 +2633,7 @@ implementation
                  { FILE can be also a type cast }
                  { FILE can be also a type cast }
                  if try_to_consume(_LKLAMMER) then
                  if try_to_consume(_LKLAMMER) then
                   begin
                   begin
-                    p1:=comp_expr(true,false);
+                    p1:=comp_expr(true,[]);
                     consume(_RKLAMMER);
                     consume(_RKLAMMER);
                     p1:=ctypeconvnode.create_explicit(p1,hdef);
                     p1:=ctypeconvnode.create_explicit(p1,hdef);
                     { handle postfix operators here e.g. string(a)[10] }
                     { handle postfix operators here e.g. string(a)[10] }
@@ -2568,7 +2677,7 @@ implementation
                  { support both @<x> and @(<x>) }
                  { support both @<x> and @(<x>) }
                  if try_to_consume(_LKLAMMER) then
                  if try_to_consume(_LKLAMMER) then
                   begin
                   begin
-                    p1:=factor(true,false);
+                    p1:=factor(true,[]);
                     if token in [_CARET,_POINT,_LECKKLAMMER] then
                     if token in [_CARET,_POINT,_LECKKLAMMER] then
                      begin
                      begin
                        again:=true;
                        again:=true;
@@ -2578,7 +2687,7 @@ implementation
                     consume(_RKLAMMER);
                     consume(_RKLAMMER);
                   end
                   end
                  else
                  else
-                  p1:=factor(true,false);
+                  p1:=factor(true,[]);
                  if token in [_CARET,_POINT,_LECKKLAMMER] then
                  if token in [_CARET,_POINT,_LECKKLAMMER] then
                   begin
                   begin
                     again:=true;
                     again:=true;
@@ -2600,7 +2709,7 @@ implementation
              _LKLAMMER :
              _LKLAMMER :
                begin
                begin
                  consume(_LKLAMMER);
                  consume(_LKLAMMER);
-                 p1:=comp_expr(true,false);
+                 p1:=comp_expr(true,[]);
                  consume(_RKLAMMER);
                  consume(_RKLAMMER);
                  { it's not a good solution     }
                  { it's not a good solution     }
                  { but (a+b)^ makes some problems  }
                  { but (a+b)^ makes some problems  }
@@ -2621,7 +2730,7 @@ implementation
              _PLUS :
              _PLUS :
                begin
                begin
                  consume(_PLUS);
                  consume(_PLUS);
-                 p1:=factor(false,false);
+                 p1:=factor(false,[]);
                  p1:=cunaryplusnode.create(p1);
                  p1:=cunaryplusnode.create(p1);
                end;
                end;
 
 
@@ -2633,7 +2742,7 @@ implementation
                       { ugly hack, but necessary to be able to parse }
                       { ugly hack, but necessary to be able to parse }
                       { -9223372036854775808 as int64 (JM)           }
                       { -9223372036854775808 as int64 (JM)           }
                       pattern := '-'+pattern;
                       pattern := '-'+pattern;
-                      p1:=sub_expr(oppower,false,false);
+                      p1:=sub_expr(oppower,false,[]);
                       {  -1 ** 4 should be - (1 ** 4) and not
                       {  -1 ** 4 should be - (1 ** 4) and not
                          (-1) ** 4
                          (-1) ** 4
                          This was the reason of tw0869.pp test failure PM }
                          This was the reason of tw0869.pp test failure PM }
@@ -2656,7 +2765,7 @@ implementation
                     end
                     end
                  else
                  else
                    begin
                    begin
-                     p1:=sub_expr(oppower,false,false);
+                     p1:=sub_expr(oppower,false,[]);
                      p1:=cunaryminusnode.create(p1);
                      p1:=cunaryminusnode.create(p1);
                    end;
                    end;
                end;
                end;
@@ -2664,7 +2773,7 @@ implementation
              _OP_NOT :
              _OP_NOT :
                begin
                begin
                  consume(_OP_NOT);
                  consume(_OP_NOT);
-                 p1:=factor(false,false);
+                 p1:=factor(false,[]);
                  p1:=cnotnode.create(p1);
                  p1:=cnotnode.create(p1);
                end;
                end;
 
 
@@ -2702,7 +2811,7 @@ implementation
                }
                }
                consume(_OBJCPROTOCOL);
                consume(_OBJCPROTOCOL);
                consume(_LKLAMMER);
                consume(_LKLAMMER);
-               p1:=factor(false,false);
+               p1:=factor(false,[]);
                consume(_RKLAMMER);
                consume(_RKLAMMER);
                p1:=cinlinenode.create(in_objc_protocol_x,false,p1);
                p1:=cinlinenode.create(in_objc_protocol_x,false,p1);
              end;
              end;
@@ -2753,7 +2862,7 @@ implementation
            _OP_AS,_OP_IS,_OP_AND,_AMPERSAND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
            _OP_AS,_OP_IS,_OP_AND,_AMPERSAND,_OP_DIV,_OP_MOD,_OP_SHL,_OP_SHR],
           [_STARSTAR] );
           [_STARSTAR] );
 
 
-    function sub_expr(pred_level:Toperator_precedence;accept_equal,typeonly:boolean):tnode;
+    function sub_expr(pred_level:Toperator_precedence;accept_equal:boolean;options:TExprOptions):tnode;
     {Reads a subexpression while the operators are of the current precedence
     {Reads a subexpression while the operators are of the current precedence
      level, or any higher level. Replaces the old term, simpl_expr and
      level, or any higher level. Replaces the old term, simpl_expr and
      simpl2_expr.}
      simpl2_expr.}
@@ -2763,9 +2872,9 @@ implementation
         filepos : tfileposinfo;
         filepos : tfileposinfo;
       begin
       begin
         if pred_level=highest_precedence then
         if pred_level=highest_precedence then
-          p1:=factor(false,typeonly)
+          p1:=factor(false,options)
         else
         else
-          p1:=sub_expr(succ(pred_level),true,typeonly);
+          p1:=sub_expr(succ(pred_level),true,options);
         repeat
         repeat
           if (token in operator_levels[pred_level]) and
           if (token in operator_levels[pred_level]) and
              ((token<>_EQ) or accept_equal) then
              ((token<>_EQ) or accept_equal) then
@@ -2774,9 +2883,9 @@ implementation
              filepos:=current_tokenpos;
              filepos:=current_tokenpos;
              consume(token);
              consume(token);
              if pred_level=highest_precedence then
              if pred_level=highest_precedence then
-               p2:=factor(false,false)
+               p2:=factor(false,[])
              else
              else
-               p2:=sub_expr(succ(pred_level),true,typeonly);
+               p2:=sub_expr(succ(pred_level),true,options);
              case oldt of
              case oldt of
                _PLUS :
                _PLUS :
                  p1:=caddnode.create(addn,p1,p2);
                  p1:=caddnode.create(addn,p1,p2);
@@ -2846,14 +2955,14 @@ implementation
       end;
       end;
 
 
 
 
-    function comp_expr(accept_equal,typeonly:boolean):tnode;
+    function comp_expr(accept_equal:boolean;options:TExprOptions):tnode;
       var
       var
          oldafterassignment : boolean;
          oldafterassignment : boolean;
          p1 : tnode;
          p1 : tnode;
       begin
       begin
          oldafterassignment:=afterassignment;
          oldafterassignment:=afterassignment;
          afterassignment:=true;
          afterassignment:=true;
-         p1:=sub_expr(opcompare,accept_equal,typeonly);
+         p1:=sub_expr(opcompare,accept_equal,options);
          { get the resultdef for this expression }
          { get the resultdef for this expression }
          if not assigned(p1.resultdef) then
          if not assigned(p1.resultdef) then
           do_typecheckpass(p1);
           do_typecheckpass(p1);
@@ -2872,7 +2981,7 @@ implementation
 
 
       begin
       begin
          oldafterassignment:=afterassignment;
          oldafterassignment:=afterassignment;
-         p1:=sub_expr(opcompare,true,false);
+         p1:=sub_expr(opcompare,true,[]);
          { get the resultdef for this expression }
          { get the resultdef for this expression }
          if not assigned(p1.resultdef) and
          if not assigned(p1.resultdef) and
             dotypecheck then
             dotypecheck then
@@ -2885,7 +2994,7 @@ implementation
            _POINTPOINT :
            _POINTPOINT :
              begin
              begin
                 consume(_POINTPOINT);
                 consume(_POINTPOINT);
-                p2:=sub_expr(opcompare,true,false);
+                p2:=sub_expr(opcompare,true,[]);
                 p1:=crangenode.create(p1,p2);
                 p1:=crangenode.create(p1,p2);
              end;
              end;
            _ASSIGNMENT :
            _ASSIGNMENT :
@@ -2893,7 +3002,7 @@ implementation
                 consume(_ASSIGNMENT);
                 consume(_ASSIGNMENT);
                 if (p1.resultdef.typ=procvardef) then
                 if (p1.resultdef.typ=procvardef) then
                   getprocvardef:=tprocvardef(p1.resultdef);
                   getprocvardef:=tprocvardef(p1.resultdef);
-                p2:=sub_expr(opcompare,true,false);
+                p2:=sub_expr(opcompare,true,[]);
                 if assigned(getprocvardef) then
                 if assigned(getprocvardef) then
                   handle_procvar(getprocvardef,p2);
                   handle_procvar(getprocvardef,p2);
                 getprocvardef:=nil;
                 getprocvardef:=nil;
@@ -2902,25 +3011,25 @@ implementation
            _PLUSASN :
            _PLUSASN :
              begin
              begin
                consume(_PLUSASN);
                consume(_PLUSASN);
-               p2:=sub_expr(opcompare,true,false);
+               p2:=sub_expr(opcompare,true,[]);
                p1:=gen_c_style_operator(addn,p1,p2);
                p1:=gen_c_style_operator(addn,p1,p2);
             end;
             end;
           _MINUSASN :
           _MINUSASN :
             begin
             begin
                consume(_MINUSASN);
                consume(_MINUSASN);
-               p2:=sub_expr(opcompare,true,false);
+               p2:=sub_expr(opcompare,true,[]);
                p1:=gen_c_style_operator(subn,p1,p2);
                p1:=gen_c_style_operator(subn,p1,p2);
             end;
             end;
           _STARASN :
           _STARASN :
             begin
             begin
                consume(_STARASN  );
                consume(_STARASN  );
-               p2:=sub_expr(opcompare,true,false);
+               p2:=sub_expr(opcompare,true,[]);
                p1:=gen_c_style_operator(muln,p1,p2);
                p1:=gen_c_style_operator(muln,p1,p2);
             end;
             end;
           _SLASHASN :
           _SLASHASN :
             begin
             begin
                consume(_SLASHASN  );
                consume(_SLASHASN  );
-               p2:=sub_expr(opcompare,true,false);
+               p2:=sub_expr(opcompare,true,[]);
                p1:=gen_c_style_operator(slashn,p1,p2);
                p1:=gen_c_style_operator(slashn,p1,p2);
             end;
             end;
           else
           else
@@ -2943,7 +3052,7 @@ implementation
       p:tnode;
       p:tnode;
     begin
     begin
       result:=0;
       result:=0;
-      p:=comp_expr(true,false);
+      p:=comp_expr(true,[]);
       if not codegenerror then
       if not codegenerror then
        begin
        begin
          if (p.nodetype<>ordconstn) or
          if (p.nodetype<>ordconstn) or
@@ -2963,7 +3072,7 @@ implementation
       p:tnode;
       p:tnode;
     begin
     begin
       get_stringconst:='';
       get_stringconst:='';
-      p:=comp_expr(true,false);
+      p:=comp_expr(true,[]);
       if p.nodetype<>stringconstn then
       if p.nodetype<>stringconstn then
         begin
         begin
           if (p.nodetype=ordconstn) and is_char(p.resultdef) then
           if (p.nodetype=ordconstn) and is_char(p.resultdef) then

+ 5 - 5
compiler/pinline.pas

@@ -76,7 +76,7 @@ implementation
         storepos : tfileposinfo;
         storepos : tfileposinfo;
       begin
       begin
         consume(_LKLAMMER);
         consume(_LKLAMMER);
-        p:=comp_expr(true,false);
+        p:=comp_expr(true,[]);
         { calc return type }
         { calc return type }
         if is_new then
         if is_new then
           begin
           begin
@@ -161,7 +161,7 @@ implementation
               begin
               begin
                  Message1(type_e_pointer_type_expected,p.resultdef.typename);
                  Message1(type_e_pointer_type_expected,p.resultdef.typename);
                  p.free;
                  p.free;
-                 p:=factor(false,false);
+                 p:=factor(false,[]);
                  p.free;
                  p.free;
                  consume(_RKLAMMER);
                  consume(_RKLAMMER);
                  new_dispose_statement:=cerrornode.create;
                  new_dispose_statement:=cerrornode.create;
@@ -172,7 +172,7 @@ implementation
               begin
               begin
                  Message(parser_e_pointer_to_class_expected);
                  Message(parser_e_pointer_to_class_expected);
                  p.free;
                  p.free;
-                 new_dispose_statement:=factor(false,false);
+                 new_dispose_statement:=factor(false,[]);
                  consume_all_until(_RKLAMMER);
                  consume_all_until(_RKLAMMER);
                  consume(_RKLAMMER);
                  consume(_RKLAMMER);
                  exit;
                  exit;
@@ -182,7 +182,7 @@ implementation
             if is_class(classh) then
             if is_class(classh) then
               begin
               begin
                  Message(parser_e_no_new_or_dispose_for_classes);
                  Message(parser_e_no_new_or_dispose_for_classes);
-                 new_dispose_statement:=factor(false,false);
+                 new_dispose_statement:=factor(false,[]);
                  consume_all_until(_RKLAMMER);
                  consume_all_until(_RKLAMMER);
                  consume(_RKLAMMER);
                  consume(_RKLAMMER);
                  exit;
                  exit;
@@ -353,7 +353,7 @@ implementation
         again  : boolean; { dummy for do_proc_call }
         again  : boolean; { dummy for do_proc_call }
       begin
       begin
         consume(_LKLAMMER);
         consume(_LKLAMMER);
-        p1:=factor(false,false);
+        p1:=factor(false,[]);
         if p1.nodetype<>typen then
         if p1.nodetype<>typen then
          begin
          begin
            Message(type_e_type_id_expected);
            Message(type_e_type_id_expected);

+ 2 - 2
compiler/pp.lpi

@@ -25,7 +25,7 @@
     <RunParams>
     <RunParams>
       <local>
       <local>
         <FormatVersion Value="1"/>
         <FormatVersion Value="1"/>
-        <CommandLineParams Value="-n @\home\florian\bin\fpc.cfg \home\florian\fpc\tests\test\cg\tsar1.pp"/>
+        <CommandLineParams Value="-B  -MObjFPC -Scghi -O1 -gl -vewnhi -l -Fic:\programming\mytest\fpctest\extended_records\operators\lib\i86-win32 -FuC:\programming\mytest\fpctest\generics\bootstrap\ -Fu. -FUc:\programming\mytest\fpctest\extended_records\operators\lib\i386-win32\ -oextended_records1.exe C:\programming\mytest\fpctest\generics\bootstrap\project1.lpr"/>
         <LaunchingApplication PathPlusParams="\usr\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
         <LaunchingApplication PathPlusParams="\usr\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
       </local>
       </local>
     </RunParams>
     </RunParams>
@@ -78,7 +78,7 @@
       <CompilerMessages>
       <CompilerMessages>
         <UseMsgFile Value="True"/>
         <UseMsgFile Value="True"/>
       </CompilerMessages>
       </CompilerMessages>
-      <CustomOptions Value="-di386"/>
+      <CustomOptions Value="-di386 -godwarfsets"/>
       <CompilerPath Value="$(CompPath)"/>
       <CompilerPath Value="$(CompPath)"/>
     </Other>
     </Other>
   </CompilerOptions>
   </CompilerOptions>

+ 12 - 12
compiler/pstatmnt.pas

@@ -71,7 +71,7 @@ implementation
          ex,if_a,else_a : tnode;
          ex,if_a,else_a : tnode;
       begin
       begin
          consume(_IF);
          consume(_IF);
-         ex:=comp_expr(true,false);
+         ex:=comp_expr(true,[]);
          consume(_THEN);
          consume(_THEN);
          if token<>_ELSE then
          if token<>_ELSE then
            if_a:=statement
            if_a:=statement
@@ -125,7 +125,7 @@ implementation
          casenode : tcasenode;
          casenode : tcasenode;
       begin
       begin
          consume(_CASE);
          consume(_CASE);
-         caseexpr:=comp_expr(true,false);
+         caseexpr:=comp_expr(true,[]);
          { determines result type }
          { determines result type }
          do_typecheckpass(caseexpr);
          do_typecheckpass(caseexpr);
          { variants must be accepted, but first they must be converted to integer }
          { variants must be accepted, but first they must be converted to integer }
@@ -300,7 +300,7 @@ implementation
          consume(_UNTIL);
          consume(_UNTIL);
 
 
          first:=cblocknode.create(first);
          first:=cblocknode.create(first);
-         p_e:=comp_expr(true,false);
+         p_e:=comp_expr(true,[]);
          result:=cwhilerepeatnode.create(p_e,first,false,true);
          result:=cwhilerepeatnode.create(p_e,first,false,true);
       end;
       end;
 
 
@@ -312,7 +312,7 @@ implementation
 
 
       begin
       begin
          consume(_WHILE);
          consume(_WHILE);
-         p_e:=comp_expr(true,false);
+         p_e:=comp_expr(true,[]);
          consume(_DO);
          consume(_DO);
          p_a:=statement;
          p_a:=statement;
          result:=cwhilerepeatnode.create(p_e,p_a,true,false);
          result:=cwhilerepeatnode.create(p_e,p_a,true,false);
@@ -424,7 +424,7 @@ implementation
              else
              else
                MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
                MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
 
 
-             hfrom:=comp_expr(true,false);
+             hfrom:=comp_expr(true,[]);
 
 
              if try_to_consume(_DOWNTO) then
              if try_to_consume(_DOWNTO) then
                backward:=true
                backward:=true
@@ -434,7 +434,7 @@ implementation
                  backward:=false;
                  backward:=false;
                end;
                end;
 
 
-             hto:=comp_expr(true,false);
+             hto:=comp_expr(true,[]);
              consume(_DO);
              consume(_DO);
 
 
              { Check if the constants fit in the range }
              { Check if the constants fit in the range }
@@ -471,7 +471,7 @@ implementation
             var
             var
               expr: tnode;
               expr: tnode;
             begin
             begin
-              expr:=comp_expr(true,false);
+              expr:=comp_expr(true,[]);
 
 
               consume(_DO);
               consume(_DO);
 
 
@@ -490,7 +490,7 @@ implementation
          { parse loop header }
          { parse loop header }
          consume(_FOR);
          consume(_FOR);
 
 
-         hloopvar:=factor(false,false);
+         hloopvar:=factor(false,[]);
          valid_for_loopvar(hloopvar,true);
          valid_for_loopvar(hloopvar,true);
 
 
          if try_to_consume(_ASSIGNMENT) then
          if try_to_consume(_ASSIGNMENT) then
@@ -533,7 +533,7 @@ implementation
 
 
 
 
       begin
       begin
-         p:=comp_expr(true,false);
+         p:=comp_expr(true,[]);
          do_typecheckpass(p);
          do_typecheckpass(p);
 
 
          if (p.nodetype=vecn) and
          if (p.nodetype=vecn) and
@@ -725,12 +725,12 @@ implementation
          if not(token in endtokens) then
          if not(token in endtokens) then
            begin
            begin
               { object }
               { object }
-              pobj:=comp_expr(true,false);
+              pobj:=comp_expr(true,[]);
               if try_to_consume(_AT) then
               if try_to_consume(_AT) then
                 begin
                 begin
-                   paddr:=comp_expr(true,false);
+                   paddr:=comp_expr(true,[]);
                    if try_to_consume(_COMMA) then
                    if try_to_consume(_COMMA) then
-                     pframe:=comp_expr(true,false);
+                     pframe:=comp_expr(true,[]);
                 end;
                 end;
            end
            end
          else
          else

+ 13 - 13
compiler/ptconst.pas

@@ -191,7 +191,7 @@ implementation
           end;
           end;
 
 
         begin
         begin
-           n:=comp_expr(true,false);
+           n:=comp_expr(true,[]);
            { for C-style booleans, true=-1 and false=0) }
            { for C-style booleans, true=-1 and false=0) }
            if is_cbool(def) then
            if is_cbool(def) then
              inserttypeconv(n,def);
              inserttypeconv(n,def);
@@ -291,7 +291,7 @@ implementation
           n : tnode;
           n : tnode;
           value : bestreal;
           value : bestreal;
         begin
         begin
-          n:=comp_expr(true,false);
+          n:=comp_expr(true,[]);
           if is_constrealnode(n) then
           if is_constrealnode(n) then
             value:=trealconstnode(n).value_real
             value:=trealconstnode(n).value_real
           else if is_constintnode(n) then
           else if is_constintnode(n) then
@@ -332,7 +332,7 @@ implementation
         var
         var
           n : tnode;
           n : tnode;
         begin
         begin
-          n:=comp_expr(true,false);
+          n:=comp_expr(true,[]);
           case n.nodetype of
           case n.nodetype of
             loadvmtaddrn:
             loadvmtaddrn:
               begin
               begin
@@ -369,7 +369,7 @@ implementation
           ll        : tasmlabel;
           ll        : tasmlabel;
           varalign  : shortint;
           varalign  : shortint;
         begin
         begin
-          p:=comp_expr(true,false);
+          p:=comp_expr(true,[]);
           { remove equal typecasts for pointer/nil addresses }
           { remove equal typecasts for pointer/nil addresses }
           if (p.nodetype=typeconvn) then
           if (p.nodetype=typeconvn) then
             with Ttypeconvnode(p) do
             with Ttypeconvnode(p) do
@@ -587,7 +587,7 @@ implementation
           p : tnode;
           p : tnode;
           i : longint;
           i : longint;
         begin
         begin
-          p:=comp_expr(true,false);
+          p:=comp_expr(true,[]);
           if p.nodetype=setconstn then
           if p.nodetype=setconstn then
             begin
             begin
               { be sure to convert to the correct result, else
               { be sure to convert to the correct result, else
@@ -622,7 +622,7 @@ implementation
         var
         var
           p : tnode;
           p : tnode;
         begin
         begin
-          p:=comp_expr(true,false);
+          p:=comp_expr(true,[]);
           if p.nodetype=ordconstn then
           if p.nodetype=ordconstn then
             begin
             begin
               if equal_defs(p.resultdef,def) or
               if equal_defs(p.resultdef,def) or
@@ -653,7 +653,7 @@ implementation
           ca        : pchar;
           ca        : pchar;
           winlike   : boolean;
           winlike   : boolean;
         begin
         begin
-          n:=comp_expr(true,false);
+          n:=comp_expr(true,[]);
           { load strval and strlength of the constant tree }
           { load strval and strlength of the constant tree }
           if (n.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(n) or
           if (n.nodetype=stringconstn) or is_wide_or_unicode_string(def) or is_constwidecharnode(n) or
             ((n.nodetype=typen) and is_interfacecorba(ttypenode(n).typedef)) then
             ((n.nodetype=typen) and is_interfacecorba(ttypenode(n).typedef)) then
@@ -772,7 +772,7 @@ implementation
             n : tnode;
             n : tnode;
           begin
           begin
             result:=true;
             result:=true;
-            n:=comp_expr(true,false);
+            n:=comp_expr(true,[]);
             if (n.nodetype <> ordconstn) or
             if (n.nodetype <> ordconstn) or
                (not equal_defs(n.resultdef,def) and
                (not equal_defs(n.resultdef,def) and
                 not is_subequal(n.resultdef,def)) then
                 not is_subequal(n.resultdef,def)) then
@@ -873,7 +873,7 @@ implementation
           else if is_anychar(def.elementdef) then
           else if is_anychar(def.elementdef) then
             begin
             begin
                char_size:=def.elementdef.size;
                char_size:=def.elementdef.size;
-               n:=comp_expr(true,false);
+               n:=comp_expr(true,[]);
                if n.nodetype=stringconstn then
                if n.nodetype=stringconstn then
                  begin
                  begin
                    len:=tstringconstnode(n).len;
                    len:=tstringconstnode(n).len;
@@ -970,7 +970,7 @@ implementation
             Message(parser_e_no_procvarobj_const);
             Message(parser_e_no_procvarobj_const);
           { parse the rest too, so we can continue with error checking }
           { parse the rest too, so we can continue with error checking }
           getprocvardef:=def;
           getprocvardef:=def;
-          n:=comp_expr(true,false);
+          n:=comp_expr(true,[]);
           getprocvardef:=nil;
           getprocvardef:=nil;
           if codegenerror then
           if codegenerror then
             begin
             begin
@@ -1062,7 +1062,7 @@ implementation
           { GUID }
           { GUID }
           if (def=rec_tguid) and (token=_ID) then
           if (def=rec_tguid) and (token=_ID) then
             begin
             begin
-              n:=comp_expr(true,false);
+              n:=comp_expr(true,[]);
               if n.nodetype=stringconstn then
               if n.nodetype=stringconstn then
                 handle_stringconstn
                 handle_stringconstn
               else
               else
@@ -1085,7 +1085,7 @@ implementation
             end;
             end;
           if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
           if (def=rec_tguid) and ((token=_CSTRING) or (token=_CCHAR)) then
             begin
             begin
-              n:=comp_expr(true,false);
+              n:=comp_expr(true,[]);
               inserttypeconv(n,cshortstringtype);
               inserttypeconv(n,cshortstringtype);
               if n.nodetype=stringconstn then
               if n.nodetype=stringconstn then
                 handle_stringconstn
                 handle_stringconstn
@@ -1278,7 +1278,7 @@ implementation
           { only allow nil for implicit pointer object types }
           { only allow nil for implicit pointer object types }
           if is_implicit_pointer_object_type(def) then
           if is_implicit_pointer_object_type(def) then
             begin
             begin
-              n:=comp_expr(true,false);
+              n:=comp_expr(true,[]);
               if n.nodetype<>niln then
               if n.nodetype<>niln then
                 begin
                 begin
                   Message(parser_e_type_const_not_possible);
                   Message(parser_e_type_const_not_possible);

+ 73 - 101
compiler/ptype.pas

@@ -40,9 +40,6 @@ interface
 
 
     procedure resolve_forward_types;
     procedure resolve_forward_types;
 
 
-    { reads a type identifier }
-    procedure id_type(var def : tdef;isforwarddef:boolean);
-
     { reads a string, file type or a type identifier }
     { reads a string, file type or a type identifier }
     procedure single_type(var def:tdef;options:TSingleTypeOptions);
     procedure single_type(var def:tdef;options:TSingleTypeOptions);
 
 
@@ -50,12 +47,12 @@ interface
     procedure read_named_type(var def:tdef;const name : TIDString;genericdef:tstoreddef;genericlist:TFPObjectList;parseprocvardir:boolean);
     procedure read_named_type(var def:tdef;const name : TIDString;genericdef:tstoreddef;genericlist:TFPObjectList;parseprocvardir:boolean);
 
 
     { reads any type declaration }
     { reads any type declaration }
-    procedure read_anon_type(var def : tdef;parseprocvardir:boolean);
+    procedure read_anon_type(var def:tdef;parseprocvardir:boolean);
 
 
     { generate persistent type information like VMT, RTTI and inittables }
     { generate persistent type information like VMT, RTTI and inittables }
     procedure write_persistent_type_info(st:tsymtable);
     procedure write_persistent_type_info(st:tsymtable);
 
 
-    procedure generate_specialization(var tt:tdef;parse_class_parent:boolean);
+    procedure generate_specialization(var tt:tdef;typeparams:TFPObjectList;parse_class_parent:boolean);
 
 
 implementation
 implementation
 
 
@@ -146,14 +143,13 @@ implementation
       end;
       end;
 
 
 
 
-    procedure generate_specialization(var tt:tdef;parse_class_parent:boolean);
+    procedure generate_specialization(var tt:tdef;typeparams:TFPObjectList;parse_class_parent:boolean);
       var
       var
         st  : TSymtable;
         st  : TSymtable;
         srsym : tsym;
         srsym : tsym;
         pt2 : tnode;
         pt2 : tnode;
-        first,
         err : boolean;
         err : boolean;
-        i   : longint;
+        i,j : longint;
         sym : tsym;
         sym : tsym;
         genericdef : tstoreddef;
         genericdef : tstoreddef;
         generictype : ttypesym;
         generictype : ttypesym;
@@ -192,25 +188,12 @@ implementation
             onlyparsepara:=true;
             onlyparsepara:=true;
           end;
           end;
 
 
-        { Only parse the parameters for recovery or
-          for recording in genericbuf }
         if onlyparsepara then
         if onlyparsepara then
-          begin
-            consume(_LSHARPBRACKET);
-            repeat
-              pt2:=factor(false,true);
-              pt2.free;
-            until not try_to_consume(_COMMA);
-            consume(_RSHARPBRACKET);
-            exit;
-          end;
+          exit;
 
 
-        if not try_to_consume(_LT) then
-          consume(_LSHARPBRACKET);
         { Parse generic parameters, for each undefineddef in the symtable of
         { Parse generic parameters, for each undefineddef in the symtable of
           the genericdef we need to have a new def }
           the genericdef we need to have a new def }
         err:=false;
         err:=false;
-        first:=true;
         generictypelist:=TFPObjectList.create(false);
         generictypelist:=TFPObjectList.create(false);
         case genericdef.typ of
         case genericdef.typ of
           procdef:
           procdef:
@@ -230,16 +213,13 @@ implementation
         if not assigned(genericdef.typesym) then
         if not assigned(genericdef.typesym) then
           internalerror(200710173);
           internalerror(200710173);
         specializename:=genericdef.typesym.realname;
         specializename:=genericdef.typesym.realname;
+        j:=0;
         for i:=0 to st.SymList.Count-1 do
         for i:=0 to st.SymList.Count-1 do
           begin
           begin
             sym:=tsym(st.SymList[i]);
             sym:=tsym(st.SymList[i]);
             if (sp_generic_para in sym.symoptions) then
             if (sp_generic_para in sym.symoptions) then
               begin
               begin
-                if not first then
-                  consume(_COMMA)
-                else
-                  first:=false;
-                pt2:=factor(false,true);
+                pt2:=tnode(typeparams[j]);
                 if pt2.nodetype=typen then
                 if pt2.nodetype=typen then
                   begin
                   begin
                     if df_generic in pt2.resultdef.defoptions then
                     if df_generic in pt2.resultdef.defoptions then
@@ -256,13 +236,10 @@ implementation
                     Message(type_e_type_id_expected);
                     Message(type_e_type_id_expected);
                     err:=true;
                     err:=true;
                   end;
                   end;
-                pt2.free;
+                inc(j);
               end;
               end;
           end;
           end;
         uspecializename:=upper(specializename);
         uspecializename:=upper(specializename);
-        { force correct error location if too much type parameters are passed }
-        if not (token in [_RSHARPBRACKET,_GT]) then
-          consume(_RSHARPBRACKET);
 
 
         { Special case if we are referencing the current defined object }
         { Special case if we are referencing the current defined object }
         if assigned(current_structdef) and
         if assigned(current_structdef) and
@@ -384,12 +361,9 @@ implementation
           end;
           end;
 
 
         generictypelist.free;
         generictypelist.free;
-        if not try_to_consume(_GT) then
-          consume(_RSHARPBRACKET);
       end;
       end;
 
 
-
-    procedure id_type(var def : tdef;isforwarddef:boolean);
+    procedure id_type(var def:tdef;options:TSingleTypeOptions;dospecialize:boolean;out typeparams:TFPObjectList);
     { reads a type definition }
     { reads a type definition }
     { to a appropriating tdef, s gets the name of   }
     { to a appropriating tdef, s gets the name of   }
     { the type to allow name mangling          }
     { the type to allow name mangling          }
@@ -398,21 +372,43 @@ implementation
         pos : tfileposinfo;
         pos : tfileposinfo;
         srsym : tsym;
         srsym : tsym;
         srsymtable : TSymtable;
         srsymtable : TSymtable;
-        s,sorg : TIDString;
+        s,sorg,generic_id_modifier : TIDString;
         t : ttoken;
         t : ttoken;
         structdef : tabstractrecorddef;
         structdef : tabstractrecorddef;
       begin
       begin
          s:=pattern;
          s:=pattern;
          sorg:=orgpattern;
          sorg:=orgpattern;
+         consume(_ID);
          pos:=current_tokenpos;
          pos:=current_tokenpos;
+         { searching a generic ? }
+         if dospecialize or
+            ((m_delphi in current_settings.modeswitches) and
+             ([stoAllowSpecialization,stoAllowTypeDef]*options<>[]) and
+             (token in [_LSHARPBRACKET,_LT])
+            ) then
+           begin
+             typeparams:=TFPObjectList.Create(true);
+             if not try_to_consume(_LSHARPBRACKET) then
+               consume(_LT);
+             repeat
+               typeparams.add(factor(false,[eoTypeOnly]));
+             until not try_to_consume(_COMMA);
+             if not try_to_consume(_RSHARPBRACKET) then
+               consume(_GT);
+             generic_id_modifier:=generate_generic_id_modifier(typeparams.count);
+             { modify patterns }
+             s:=s+generic_id_modifier;
+             sorg:=sorg+generic_id_modifier;
+           end
+         else
+           typeparams:=nil;
          { use of current parsed object:
          { use of current parsed object:
            classes, objects, records can be used also in themself }
            classes, objects, records can be used also in themself }
          structdef:=current_structdef;
          structdef:=current_structdef;
          while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
          while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
            begin
            begin
-             if (structdef.objname^=pattern) then
+             if (structdef.objname^=s) then
                begin
                begin
-                 consume(_ID);
                  def:=structdef;
                  def:=structdef;
                  exit;
                  exit;
                end;
                end;
@@ -421,8 +417,9 @@ implementation
          { Use the special searchsym_type that search only types }
          { Use the special searchsym_type that search only types }
          searchsym_type(s,srsym,srsymtable);
          searchsym_type(s,srsym,srsymtable);
          { handle unit specification like System.Writeln }
          { handle unit specification like System.Writeln }
-         is_unit_specific:=try_consume_unitsym(srsym,srsymtable,t);
-         consume(t);
+         is_unit_specific:=try_consume_unitsym(srsym,srsymtable,t,false);
+         if is_unit_specific then
+           consume(t);
          { Types are first defined with an error def before assigning
          { Types are first defined with an error def before assigning
            the real type so check if it's an errordef. if so then
            the real type so check if it's an errordef. if so then
            give an error. Only check for typesyms in the current symbol
            give an error. Only check for typesyms in the current symbol
@@ -436,7 +433,7 @@ implementation
             exit;
             exit;
           end;
           end;
          { are we parsing a possible forward def ? }
          { are we parsing a possible forward def ? }
-         if isforwarddef and
+         if (stoIsForwardDef in options) and
             not(is_unit_specific) then
             not(is_unit_specific) then
            begin
            begin
              def:=tforwarddef.create(sorg,pos);
              def:=tforwarddef.create(sorg,pos);
@@ -469,11 +466,12 @@ implementation
 
 
     procedure single_type(var def:tdef;options:TSingleTypeOptions);
     procedure single_type(var def:tdef;options:TSingleTypeOptions);
        var
        var
-         t2 : tdef;
-         dospecialize,
-         again : boolean;
+         t2: tdef;
+         dospecialize,again: boolean;
+         typeparams: TFPObjectList;
        begin
        begin
          dospecialize:=false;
          dospecialize:=false;
+         typeparams:=nil;
          repeat
          repeat
            again:=false;
            again:=false;
              case token of
              case token of
@@ -518,7 +516,7 @@ implementation
                      end
                      end
                    else
                    else
                      begin
                      begin
-                       id_type(def,stoIsForwardDef in options);
+                       id_type(def,options,dospecialize,typeparams);
                        { handle types inside classes, e.g. TNode.TLongint }
                        { handle types inside classes, e.g. TNode.TLongint }
                        while (token=_POINT) do
                        while (token=_POINT) do
                          begin
                          begin
@@ -531,7 +529,7 @@ implementation
                               begin
                               begin
                                 symtablestack.push(tabstractrecorddef(def).symtable);
                                 symtablestack.push(tabstractrecorddef(def).symtable);
                                 consume(_POINT);
                                 consume(_POINT);
-                                id_type(t2,stoIsForwardDef in options);
+                                id_type(t2,options,dospecialize,typeparams);
                                 symtablestack.pop(tabstractrecorddef(def).symtable);
                                 symtablestack.pop(tabstractrecorddef(def).symtable);
                                 def:=t2;
                                 def:=t2;
                               end
                               end
@@ -548,11 +546,8 @@ implementation
                  end;
                  end;
             end;
             end;
         until not again;
         until not again;
-        if ([stoAllowSpecialization,stoAllowTypeDef] * options <> []) and
-           (m_delphi in current_settings.modeswitches) then
-          dospecialize:=token=_LSHARPBRACKET;
-        if dospecialize then
-          generate_specialization(def,stoParseClassParent in options)
+        if assigned(typeparams) then
+          generate_specialization(def,typeparams,stoParseClassParent in options)
         else
         else
           begin
           begin
             if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
             if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
@@ -574,6 +569,7 @@ implementation
                 def:=generrordef
                 def:=generrordef
               end
               end
           end;
           end;
+        typeparams.free;
       end;
       end;
 
 
     procedure parse_record_members;
     procedure parse_record_members;
@@ -933,40 +929,24 @@ implementation
         defpos,storepos : tfileposinfo;
         defpos,storepos : tfileposinfo;
 
 
         procedure expr_type;
         procedure expr_type;
+        const
+          expr_options:array[boolean]of TExprOptions=([eoTypeOnly],[eoTypeOnly,eoSpecialize]);
         var
         var
            pt1,pt2 : tnode;
            pt1,pt2 : tnode;
            lv,hv   : TConstExprInt;
            lv,hv   : TConstExprInt;
            old_block_type : tblock_type;
            old_block_type : tblock_type;
-           dospecialize : boolean;
-           structdef: tabstractrecorddef;
+           options: TExprOptions;
         begin
         begin
            old_block_type:=block_type;
            old_block_type:=block_type;
-           dospecialize:=false;
-           { use of current parsed object:
-             classes, objects, records can be used also in themself }
-           if (token=_ID) then
-             begin
-               structdef:=current_structdef;
-               while assigned(structdef) and (structdef.typ in [objectdef,recorddef]) do
-                 begin
-                   if (structdef.objname^=pattern) then
-                     begin
-                       consume(_ID);
-                       def:=structdef;
-                       exit;
-                     end;
-                   structdef:=tabstractrecorddef(structdef.owner.defowner);
-                 end;
-             end;
            { Generate a specialization in FPC mode? }
            { Generate a specialization in FPC mode? }
-           dospecialize:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_SPECIALIZE);
+           options:=expr_options[not(m_delphi in current_settings.modeswitches) and try_to_consume(_SPECIALIZE)];
            { we can't accept a equal in type }
            { we can't accept a equal in type }
-           pt1:=comp_expr(false,true);
-           if not dospecialize and
+           pt1:=comp_expr(false,options);
+           if not (eoSpecialize in options) and
               try_to_consume(_POINTPOINT) then
               try_to_consume(_POINTPOINT) then
              begin
              begin
                { get high value of range }
                { get high value of range }
-               pt2:=comp_expr(false,false);
+               pt2:=comp_expr(false,[]);
                { make both the same type or give an error. This is not
                { make both the same type or give an error. This is not
                  done when both are integer values, because typecasting
                  done when both are integer values, because typecasting
                  between -3200..3200 will result in a signed-unsigned
                  between -3200..3200 will result in a signed-unsigned
@@ -1015,32 +995,24 @@ implementation
                if (pt1.nodetype=typen) then
                if (pt1.nodetype=typen) then
                  begin
                  begin
                    def:=ttypenode(pt1).resultdef;
                    def:=ttypenode(pt1).resultdef;
-                   { Delphi mode specialization? }
-                   if (m_delphi in current_settings.modeswitches) then
-                     dospecialize:=token=_LSHARPBRACKET;
-                   if dospecialize then
-                     generate_specialization(def,false)
-                   else
+                   if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
                      begin
                      begin
-                       if assigned(current_specializedef) and (def=current_specializedef.genericdef) then
-                         begin
-                           def:=current_specializedef
-                         end
-                       else if (def=current_genericdef) then
-                         begin
-                           def:=current_genericdef
-                         end
-                       else if (df_generic in def.defoptions) then
-                         begin
-                           Message(parser_e_no_generics_as_types);
-                           def:=generrordef;
-                         end
-                       else if is_objccategory(def) then
-                         begin
-                           Message(parser_e_no_category_as_types);
-                           def:=generrordef
-                         end
-                     end;
+                       def:=current_specializedef
+                     end
+                   else if (def=current_genericdef) then
+                     begin
+                       def:=current_genericdef
+                     end
+                   else if (df_generic in def.defoptions) then
+                     begin
+                       Message(parser_e_no_generics_as_types);
+                       def:=generrordef;
+                     end
+                   else if is_objccategory(def) then
+                     begin
+                       Message(parser_e_no_category_as_types);
+                       def:=generrordef
+                     end
                  end
                  end
                else
                else
                  Message(sym_e_error_in_type_def);
                  Message(sym_e_error_in_type_def);
@@ -1411,7 +1383,7 @@ implementation
                     begin
                     begin
                        oldlocalswitches:=current_settings.localswitches;
                        oldlocalswitches:=current_settings.localswitches;
                        include(current_settings.localswitches,cs_allow_enum_calc);
                        include(current_settings.localswitches,cs_allow_enum_calc);
-                       p:=comp_expr(true,false);
+                       p:=comp_expr(true,[]);
                        current_settings.localswitches:=oldlocalswitches;
                        current_settings.localswitches:=oldlocalswitches;
                        if (p.nodetype=ordconstn) then
                        if (p.nodetype=ordconstn) then
                         begin
                         begin
@@ -1616,7 +1588,7 @@ implementation
       end;
       end;
 
 
 
 
-    procedure read_anon_type(var def : tdef;parseprocvardir:boolean);
+    procedure read_anon_type(var def:tdef;parseprocvardir:boolean);
       begin
       begin
         read_named_type(def,'',nil,nil,parseprocvardir);
         read_named_type(def,'',nil,nil,parseprocvardir);
       end;
       end;

+ 57 - 0
compiler/scanner.pas

@@ -74,6 +74,22 @@ interface
          constructor Create(atoken: ttoken;asettings:tsettings;atokenbuf:tdynamicarray;anext:treplaystack);
          constructor Create(atoken: ttoken;asettings:tsettings;atokenbuf:tdynamicarray;anext:treplaystack);
        end;
        end;
 
 
+       tscannerstate = record
+         token: ttoken;
+         idtoken: ttoken;
+         settings: tsettings;
+         orgpattern: string;
+         pattern: string;
+         lasttokenpos: longint;
+         current_filepos: tfileposinfo;
+         current_tokenpos: tfileposinfo;
+         line_no: longint;
+         lastlinepos: longint;
+         bufstart: longint;
+         inputpos: longint;
+         c: char;
+       end;
+
        tcompile_time_predicate = function(var valuedescr: String) : Boolean;
        tcompile_time_predicate = function(var valuedescr: String) : Boolean;
 
 
        tspecialgenerictoken = (ST_LOADSETTINGS,ST_LINE,ST_COLUMN,ST_FILEINDEX);
        tspecialgenerictoken = (ST_LOADSETTINGS,ST_LINE,ST_COLUMN,ST_FILEINDEX);
@@ -181,6 +197,9 @@ interface
           function  readpreproc:ttoken;
           function  readpreproc:ttoken;
           function  asmgetcharstart : char;
           function  asmgetcharstart : char;
           function  asmgetchar:char;
           function  asmgetchar:char;
+          { state save restore }
+          function savestate:tscannerstate;
+          procedure restorestate(state:tscannerstate);
        end;
        end;
 
 
 {$ifdef PREPROCWRITE}
 {$ifdef PREPROCWRITE}
@@ -4318,6 +4337,44 @@ exit_label:
          until false;
          until false;
       end;
       end;
 
 
+    function tscannerfile.savestate:tscannerstate;
+      begin
+        result.settings:=current_settings;
+        result.token:=token;
+        result.idtoken:=idtoken;
+        result.pattern:=pattern;
+        result.orgpattern:=orgpattern;
+        result.lasttokenpos:=lasttokenpos;
+        result.current_filepos:=current_filepos;
+        result.current_tokenpos:=current_tokenpos;
+        result.line_no:=line_no;
+        result.lastlinepos:=lastlinepos;
+        result.bufstart:=inputfile.bufstart;
+        result.inputpos:=inputpointer-inputbuffer;
+        result.c:=c;
+      end;
+
+    procedure tscannerfile.restorestate(state:tscannerstate);
+      begin
+        current_settings:=state.settings;
+        token:=state.token;
+        idtoken:=state.idtoken;
+        pattern:=state.pattern;
+        orgpattern:=state.orgpattern;
+        lasttokenpos:=state.lasttokenpos;
+        current_filepos:=state.current_filepos;
+        current_tokenpos:=state.current_tokenpos;
+        line_no:=state.line_no;
+        lastlinepos:=state.lastlinepos;
+        c:=state.c;
+        if inputfile.bufstart<>state.bufstart then
+          begin
+            inputfile.seekbuf(state.bufstart);
+            inputfile.readbuf;
+            inputbuffer:=inputfile.buf;
+          end;
+        inputpointer:=inputbuffer+state.inputpos;
+      end;
 
 
 {*****************************************************************************
 {*****************************************************************************
                                    Helpers
                                    Helpers

+ 11 - 1
compiler/symtable.pas

@@ -206,6 +206,7 @@ interface
 {*** Misc ***}
 {*** Misc ***}
     function  FullTypeName(def,otherdef:tdef):string;
     function  FullTypeName(def,otherdef:tdef):string;
     function generate_nested_name(symtable:tsymtable;delimiter:string):string;
     function generate_nested_name(symtable:tsymtable;delimiter:string):string;
+    function generate_generic_id_modifier(const typeparamcount:integer):string;
     procedure incompatibletypes(def1,def2:tdef);
     procedure incompatibletypes(def1,def2:tdef);
     procedure hidesym(sym:TSymEntry);
     procedure hidesym(sym:TSymEntry);
     procedure duplicatesym(var hashedid:THashedIDString;dupsym,origsym:TSymEntry);
     procedure duplicatesym(var hashedid:THashedIDString;dupsym,origsym:TSymEntry);
@@ -1700,6 +1701,15 @@ implementation
           end;
           end;
       end;
       end;
 
 
+    function generate_generic_id_modifier(const typeparamcount:integer):string;
+      begin
+        SetLength(Result,typeparamcount+1);
+        if typeparamcount>1 then
+          FillChar(Result[2],typeparamcount-1,',');
+        Result[1]:='<';
+        Result[typeparamcount+1]:='>';
+      end;
+
     procedure incompatibletypes(def1,def2:tdef);
     procedure incompatibletypes(def1,def2:tdef);
       begin
       begin
         { When there is an errordef there is already an error message show }
         { When there is an errordef there is already an error message show }
@@ -2003,7 +2013,7 @@ implementation
       end;
       end;
 
 
 
 
-    function searchsym_in_module(pm:pointer;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
+    function searchsym_in_module(pm:pointer;const s:TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
       var
       var
         pmod : tmodule;
         pmod : tmodule;
       begin
       begin

+ 121 - 121
rtl/objpas/fgl.pp

@@ -124,9 +124,9 @@ type
     function IndexOf(const Item: T): Integer;
     function IndexOf(const Item: T): Integer;
     procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
     procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
     function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
     function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
-{$ifndef VER2_4}
-    procedure Assign(Source: TFPGList);
-{$endif VER2_4}
+{$ifndef OldSyntax}
+    procedure Assign(Source: specialize TFPGList<T>);
+{$endif OldSyntax}
     function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
     function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
     procedure Sort(Compare: TCompareFunc);
     procedure Sort(Compare: TCompareFunc);
     property Items[Index: Integer]: T read Get write Put; default;
     property Items[Index: Integer]: T read Get write Put; default;
@@ -159,9 +159,9 @@ type
     function IndexOf(const Item: T): Integer;
     function IndexOf(const Item: T): Integer;
     procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
     procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
     function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
     function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
-{$ifndef VER2_4}
-    procedure Assign(Source: TFPGObjectList);
-{$endif VER2_4}
+{$ifndef OldSyntax}
+    procedure Assign(Source: specialize TFPGObjectList<T>);
+{$endif OldSyntax}
     function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
     function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
     procedure Sort(Compare: TCompareFunc);
     procedure Sort(Compare: TCompareFunc);
     property Items[Index: Integer]: T read Get write Put; default;
     property Items[Index: Integer]: T read Get write Put; default;
@@ -194,9 +194,9 @@ type
     function IndexOf(const Item: T): Integer;
     function IndexOf(const Item: T): Integer;
     procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
     procedure Insert(Index: Integer; const Item: T); {$ifdef CLASSESINLINE} inline; {$endif}
     function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
     function Last: T; {$ifdef CLASSESINLINE} inline; {$endif}
-{$ifndef VER2_4}
-    procedure Assign(Source: TFPGInterfacedObjectList);
-{$endif VER2_4}
+{$ifndef OldSyntax}
+    procedure Assign(Source: specialize TFPGInterfacedObjectList<T>);
+{$endif OldSyntax}
     function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
     function Remove(const Item: T): Integer; {$ifdef CLASSESINLINE} inline; {$endif}
     procedure Sort(Compare: TCompareFunc);
     procedure Sort(Compare: TCompareFunc);
     property Items[Index: Integer]: T read Get write Put; default;
     property Items[Index: Integer]: T read Get write Put; default;
@@ -694,19 +694,19 @@ end;
 {*             TFPGListEnumerator                                           *}
 {*             TFPGListEnumerator                                           *}
 {****************************************************************************}
 {****************************************************************************}
 
 
-function TFPGListEnumerator.GetCurrent: T;
+function TFPGListEnumerator{$ifndef OldSyntax}<T>{$endif}.GetCurrent: T;
 begin
 begin
   Result := T(FList.Items[FPosition]^);
   Result := T(FList.Items[FPosition]^);
 end;
 end;
 
 
-constructor TFPGListEnumerator.Create(AList: TFPSList);
+constructor TFPGListEnumerator{$ifndef OldSyntax}<T>{$endif}.Create(AList: TFPSList);
 begin
 begin
   inherited Create;
   inherited Create;
   FList := AList;
   FList := AList;
   FPosition := -1;
   FPosition := -1;
 end;
 end;
 
 
-function TFPGListEnumerator.MoveNext: Boolean;
+function TFPGListEnumerator{$ifndef OldSyntax}<T>{$endif}.MoveNext: Boolean;
 begin
 begin
   inc(FPosition);
   inc(FPosition);
   Result := FPosition < FList.Count;
   Result := FPosition < FList.Count;
@@ -716,47 +716,47 @@ end;
 {*                TFPGList                                                  *}
 {*                TFPGList                                                  *}
 {****************************************************************************}
 {****************************************************************************}
 
 
-constructor TFPGList.Create;
+constructor TFPGList{$ifndef OldSyntax}<T>{$endif}.Create;
 begin
 begin
   inherited Create(sizeof(T));
   inherited Create(sizeof(T));
 end;
 end;
 
 
-procedure TFPGList.CopyItem(Src, Dest: Pointer);
+procedure TFPGList{$ifndef OldSyntax}<T>{$endif}.CopyItem(Src, Dest: Pointer);
 begin
 begin
   T(Dest^) := T(Src^);
   T(Dest^) := T(Src^);
 end;
 end;
 
 
-procedure TFPGList.Deref(Item: Pointer);
+procedure TFPGList{$ifndef OldSyntax}<T>{$endif}.Deref(Item: Pointer);
 begin
 begin
   Finalize(T(Item^));
   Finalize(T(Item^));
 end;
 end;
 
 
-function TFPGList.Get(Index: Integer): T;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.Get(Index: Integer): T;
 begin
 begin
   Result := T(inherited Get(Index)^);
   Result := T(inherited Get(Index)^);
 end;
 end;
 
 
-function TFPGList.GetList: PTypeList;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.GetList: PTypeList;
 begin
 begin
   Result := PTypeList(FList);
   Result := PTypeList(FList);
 end;
 end;
 
 
-function TFPGList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.ItemPtrCompare(Item1, Item2: Pointer): Integer;
 begin
 begin
   Result := FOnCompare(T(Item1^), T(Item2^));
   Result := FOnCompare(T(Item1^), T(Item2^));
 end;
 end;
 
 
-procedure TFPGList.Put(Index: Integer; const Item: T);
+procedure TFPGList{$ifndef OldSyntax}<T>{$endif}.Put(Index: Integer; const Item: T);
 begin
 begin
   inherited Put(Index, @Item);
   inherited Put(Index, @Item);
 end;
 end;
 
 
-function TFPGList.Add(const Item: T): Integer;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.Add(const Item: T): Integer;
 begin
 begin
   Result := inherited Add(@Item);
   Result := inherited Add(@Item);
 end;
 end;
 
 
-function TFPGList.Extract(const Item: T): T;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.Extract(const Item: T): T;
 var
 var
   ResPtr: Pointer;
   ResPtr: Pointer;
 begin
 begin
@@ -767,17 +767,17 @@ begin
     FillByte(Result, sizeof(T), 0);
     FillByte(Result, sizeof(T), 0);
 end;
 end;
 
 
-function TFPGList.First: T;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.First: T;
 begin
 begin
   Result := T(inherited First^);
   Result := T(inherited First^);
 end;
 end;
 
 
-function TFPGList.GetEnumerator: TFPGListEnumeratorSpec;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.GetEnumerator: TFPGListEnumeratorSpec;
 begin
 begin
   Result := TFPGListEnumeratorSpec.Create(Self);
   Result := TFPGListEnumeratorSpec.Create(Self);
 end;
 end;
 
 
-function TFPGList.IndexOf(const Item: T): Integer;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.IndexOf(const Item: T): Integer;
 begin
 begin
   Result := 0;
   Result := 0;
   {$info TODO: fix inlining to work! InternalItems[Result]^}
   {$info TODO: fix inlining to work! InternalItems[Result]^}
@@ -787,18 +787,18 @@ begin
     Result := -1;
     Result := -1;
 end;
 end;
 
 
-procedure TFPGList.Insert(Index: Integer; const Item: T);
+procedure TFPGList{$ifndef OldSyntax}<T>{$endif}.Insert(Index: Integer; const Item: T);
 begin
 begin
   T(inherited Insert(Index)^) := Item;
   T(inherited Insert(Index)^) := Item;
 end;
 end;
 
 
-function TFPGList.Last: T;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.Last: T;
 begin
 begin
   Result := T(inherited Last^);
   Result := T(inherited Last^);
 end;
 end;
 
 
-{$ifndef VER2_4}
-procedure TFPGList.Assign(Source: TFPGList);
+{$ifndef OldSyntax}
+procedure TFPGList<T>.Assign(Source: specialize TFPGList<T>);
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
@@ -806,16 +806,16 @@ begin
   for I := 0 to Source.Count - 1 do
   for I := 0 to Source.Count - 1 do
     Add(Source[i]);
     Add(Source[i]);
 end;
 end;
-{$endif VER2_4}
+{$endif OldSyntax}
 
 
-function TFPGList.Remove(const Item: T): Integer;
+function TFPGList{$ifndef OldSyntax}<T>{$endif}.Remove(const Item: T): Integer;
 begin
 begin
   Result := IndexOf(Item);
   Result := IndexOf(Item);
   if Result >= 0 then
   if Result >= 0 then
     Delete(Result);
     Delete(Result);
 end;
 end;
 
 
-procedure TFPGList.Sort(Compare: TCompareFunc);
+procedure TFPGList{$ifndef OldSyntax}<T>{$endif}.Sort(Compare: TCompareFunc);
 begin
 begin
   FOnCompare := Compare;
   FOnCompare := Compare;
   inherited Sort(@ItemPtrCompare);
   inherited Sort(@ItemPtrCompare);
@@ -826,49 +826,49 @@ end;
 {*                TFPGObjectList                                            *}
 {*                TFPGObjectList                                            *}
 {****************************************************************************}
 {****************************************************************************}
 
 
-constructor TFPGObjectList.Create(FreeObjects: Boolean);
+constructor TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Create(FreeObjects: Boolean);
 begin
 begin
   inherited Create;
   inherited Create;
   FFreeObjects := FreeObjects;
   FFreeObjects := FreeObjects;
 end;
 end;
 
 
-procedure TFPGObjectList.CopyItem(Src, Dest: Pointer);
+procedure TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.CopyItem(Src, Dest: Pointer);
 begin
 begin
   T(Dest^) := T(Src^);
   T(Dest^) := T(Src^);
 end;
 end;
 
 
-procedure TFPGObjectList.Deref(Item: Pointer);
+procedure TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Deref(Item: Pointer);
 begin
 begin
   if FFreeObjects then
   if FFreeObjects then
     T(Item^).Free;
     T(Item^).Free;
 end;
 end;
 
 
-function TFPGObjectList.Get(Index: Integer): T;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Get(Index: Integer): T;
 begin
 begin
   Result := T(inherited Get(Index)^);
   Result := T(inherited Get(Index)^);
 end;
 end;
 
 
-function TFPGObjectList.GetList: PTypeList;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.GetList: PTypeList;
 begin
 begin
   Result := PTypeList(FList);
   Result := PTypeList(FList);
 end;
 end;
 
 
-function TFPGObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.ItemPtrCompare(Item1, Item2: Pointer): Integer;
 begin
 begin
   Result := FOnCompare(T(Item1^), T(Item2^));
   Result := FOnCompare(T(Item1^), T(Item2^));
 end;
 end;
 
 
-procedure TFPGObjectList.Put(Index: Integer; const Item: T);
+procedure TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Put(Index: Integer; const Item: T);
 begin
 begin
   inherited Put(Index, @Item);
   inherited Put(Index, @Item);
 end;
 end;
 
 
-function TFPGObjectList.Add(const Item: T): Integer;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Add(const Item: T): Integer;
 begin
 begin
   Result := inherited Add(@Item);
   Result := inherited Add(@Item);
 end;
 end;
 
 
-function TFPGObjectList.Extract(const Item: T): T;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Extract(const Item: T): T;
 var
 var
   ResPtr: Pointer;
   ResPtr: Pointer;
 begin
 begin
@@ -879,17 +879,17 @@ begin
     FillByte(Result, sizeof(T), 0);
     FillByte(Result, sizeof(T), 0);
 end;
 end;
 
 
-function TFPGObjectList.First: T;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.First: T;
 begin
 begin
   Result := T(inherited First^);
   Result := T(inherited First^);
 end;
 end;
 
 
-function TFPGObjectList.GetEnumerator: TFPGListEnumeratorSpec;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.GetEnumerator: TFPGListEnumeratorSpec;
 begin
 begin
   Result := TFPGListEnumeratorSpec.Create(Self);
   Result := TFPGListEnumeratorSpec.Create(Self);
 end;
 end;
 
 
-function TFPGObjectList.IndexOf(const Item: T): Integer;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.IndexOf(const Item: T): Integer;
 begin
 begin
   Result := 0;
   Result := 0;
   {$info TODO: fix inlining to work! InternalItems[Result]^}
   {$info TODO: fix inlining to work! InternalItems[Result]^}
@@ -899,18 +899,18 @@ begin
     Result := -1;
     Result := -1;
 end;
 end;
 
 
-procedure TFPGObjectList.Insert(Index: Integer; const Item: T);
+procedure TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Insert(Index: Integer; const Item: T);
 begin
 begin
   T(inherited Insert(Index)^) := Item;
   T(inherited Insert(Index)^) := Item;
 end;
 end;
 
 
-function TFPGObjectList.Last: T;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Last: T;
 begin
 begin
   Result := T(inherited Last^);
   Result := T(inherited Last^);
 end;
 end;
 
 
-{$ifndef VER2_4}
-procedure TFPGObjectList.Assign(Source: TFPGObjectList);
+{$ifndef OldSyntax}
+procedure TFPGObjectList<T>.Assign(Source: specialize TFPGObjectList<T>);
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
@@ -918,16 +918,16 @@ begin
   for I := 0 to Source.Count - 1 do
   for I := 0 to Source.Count - 1 do
     Add(Source[i]);
     Add(Source[i]);
 end;
 end;
-{$endif VER2_4}
+{$endif OldSyntax}
 
 
-function TFPGObjectList.Remove(const Item: T): Integer;
+function TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Remove(const Item: T): Integer;
 begin
 begin
   Result := IndexOf(Item);
   Result := IndexOf(Item);
   if Result >= 0 then
   if Result >= 0 then
     Delete(Result);
     Delete(Result);
 end;
 end;
 
 
-procedure TFPGObjectList.Sort(Compare: TCompareFunc);
+procedure TFPGObjectList{$ifndef OldSyntax}<T>{$endif}.Sort(Compare: TCompareFunc);
 begin
 begin
   FOnCompare := Compare;
   FOnCompare := Compare;
   inherited Sort(@ItemPtrCompare);
   inherited Sort(@ItemPtrCompare);
@@ -938,12 +938,12 @@ end;
 {*                TFPGInterfacedObjectList                                  *}
 {*                TFPGInterfacedObjectList                                  *}
 {****************************************************************************}
 {****************************************************************************}
 
 
-constructor TFPGInterfacedObjectList.Create;
+constructor TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Create;
 begin
 begin
   inherited Create;
   inherited Create;
 end;
 end;
 
 
-procedure TFPGInterfacedObjectList.CopyItem(Src, Dest: Pointer);
+procedure TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.CopyItem(Src, Dest: Pointer);
 begin
 begin
   if Assigned(Pointer(Dest^)) then
   if Assigned(Pointer(Dest^)) then
     T(Dest^)._Release;
     T(Dest^)._Release;
@@ -952,38 +952,38 @@ begin
     T(Dest^)._AddRef;
     T(Dest^)._AddRef;
 end;
 end;
 
 
-procedure TFPGInterfacedObjectList.Deref(Item: Pointer);
+procedure TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Deref(Item: Pointer);
 begin
 begin
   if Assigned(Pointer(Item^)) then
   if Assigned(Pointer(Item^)) then
     T(Item^)._Release;
     T(Item^)._Release;
 end;
 end;
 
 
-function TFPGInterfacedObjectList.Get(Index: Integer): T;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Get(Index: Integer): T;
 begin
 begin
   Result := T(inherited Get(Index)^);
   Result := T(inherited Get(Index)^);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.GetList: PTypeList;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.GetList: PTypeList;
 begin
 begin
   Result := PTypeList(FList);
   Result := PTypeList(FList);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.ItemPtrCompare(Item1, Item2: Pointer): Integer;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.ItemPtrCompare(Item1, Item2: Pointer): Integer;
 begin
 begin
   Result := FOnCompare(T(Item1^), T(Item2^));
   Result := FOnCompare(T(Item1^), T(Item2^));
 end;
 end;
 
 
-procedure TFPGInterfacedObjectList.Put(Index: Integer; const Item: T);
+procedure TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Put(Index: Integer; const Item: T);
 begin
 begin
   inherited Put(Index, @Item);
   inherited Put(Index, @Item);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.Add(const Item: T): Integer;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Add(const Item: T): Integer;
 begin
 begin
   Result := inherited Add(@Item);
   Result := inherited Add(@Item);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.Extract(const Item: T): T;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Extract(const Item: T): T;
 var
 var
   ResPtr: Pointer;
   ResPtr: Pointer;
 begin
 begin
@@ -994,17 +994,17 @@ begin
     FillByte(Result, sizeof(T), 0);
     FillByte(Result, sizeof(T), 0);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.First: T;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.First: T;
 begin
 begin
   Result := T(inherited First^);
   Result := T(inherited First^);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.GetEnumerator: TFPGListEnumeratorSpec;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.GetEnumerator: TFPGListEnumeratorSpec;
 begin
 begin
   Result := TFPGListEnumeratorSpec.Create(Self);
   Result := TFPGListEnumeratorSpec.Create(Self);
 end;
 end;
 
 
-function TFPGInterfacedObjectList.IndexOf(const Item: T): Integer;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.IndexOf(const Item: T): Integer;
 begin
 begin
   Result := 0;
   Result := 0;
   {$info TODO: fix inlining to work! InternalItems[Result]^}
   {$info TODO: fix inlining to work! InternalItems[Result]^}
@@ -1014,18 +1014,18 @@ begin
     Result := -1;
     Result := -1;
 end;
 end;
 
 
-procedure TFPGInterfacedObjectList.Insert(Index: Integer; const Item: T);
+procedure TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Insert(Index: Integer; const Item: T);
 begin
 begin
   T(inherited Insert(Index)^) := Item;
   T(inherited Insert(Index)^) := Item;
 end;
 end;
 
 
-function TFPGInterfacedObjectList.Last: T;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Last: T;
 begin
 begin
   Result := T(inherited Last^);
   Result := T(inherited Last^);
 end;
 end;
 
 
-{$ifndef VER2_4}
-procedure TFPGInterfacedObjectList.Assign(Source: TFPGInterfacedObjectList);
+{$ifndef OldSyntax}
+procedure TFPGInterfacedObjectList<T>.Assign(Source: specialize TFPGInterfacedObjectList<T>);
 var
 var
   i: Integer;
   i: Integer;
 begin
 begin
@@ -1033,16 +1033,16 @@ begin
   for I := 0 to Source.Count - 1 do
   for I := 0 to Source.Count - 1 do
     Add(Source[i]);
     Add(Source[i]);
 end;
 end;
-{$endif VER2_4}
+{$endif OldSyntax}
 
 
-function TFPGInterfacedObjectList.Remove(const Item: T): Integer;
+function TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Remove(const Item: T): Integer;
 begin
 begin
   Result := IndexOf(Item);
   Result := IndexOf(Item);
   if Result >= 0 then
   if Result >= 0 then
     Delete(Result);
     Delete(Result);
 end;
 end;
 
 
-procedure TFPGInterfacedObjectList.Sort(Compare: TCompareFunc);
+procedure TFPGInterfacedObjectList{$ifndef OldSyntax}<T>{$endif}.Sort(Compare: TCompareFunc);
 begin
 begin
   FOnCompare := Compare;
   FOnCompare := Compare;
   inherited Sort(@ItemPtrCompare);
   inherited Sort(@ItemPtrCompare);
@@ -1283,49 +1283,49 @@ end;
                              TFPGMap
                              TFPGMap
  ****************************************************************************}
  ****************************************************************************}
 
 
-constructor TFPGMap.Create;
+constructor TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.Create;
 begin
 begin
   inherited Create(SizeOf(TKey), SizeOf(TData));
   inherited Create(SizeOf(TKey), SizeOf(TData));
 end;
 end;
 
 
-procedure TFPGMap.CopyItem(Src, Dest: Pointer);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.CopyItem(Src, Dest: Pointer);
 begin
 begin
   CopyKey(Src, Dest);
   CopyKey(Src, Dest);
   CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
   CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
 end;
 end;
 
 
-procedure TFPGMap.CopyKey(Src, Dest: Pointer);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.CopyKey(Src, Dest: Pointer);
 begin
 begin
   TKey(Dest^) := TKey(Src^);
   TKey(Dest^) := TKey(Src^);
 end;
 end;
 
 
-procedure TFPGMap.CopyData(Src, Dest: Pointer);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.CopyData(Src, Dest: Pointer);
 begin
 begin
   TData(Dest^) := TData(Src^);
   TData(Dest^) := TData(Src^);
 end;
 end;
 
 
-procedure TFPGMap.Deref(Item: Pointer);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.Deref(Item: Pointer);
 begin
 begin
   Finalize(TKey(Item^));
   Finalize(TKey(Item^));
   Finalize(TData(Pointer(PByte(Item)+KeySize)^));
   Finalize(TData(Pointer(PByte(Item)+KeySize)^));
 end;
 end;
 
 
-function TFPGMap.GetKey(Index: Integer): TKey;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.GetKey(Index: Integer): TKey;
 begin
 begin
   Result := TKey(inherited GetKey(Index)^);
   Result := TKey(inherited GetKey(Index)^);
 end;
 end;
 
 
-function TFPGMap.GetData(Index: Integer): TData;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.GetData(Index: Integer): TData;
 begin
 begin
   Result := TData(inherited GetData(Index)^);
   Result := TData(inherited GetData(Index)^);
 end;
 end;
 
 
-function TFPGMap.GetKeyData(const AKey: TKey): TData;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.GetKeyData(const AKey: TKey): TData;
 begin
 begin
   Result := TData(inherited GetKeyData(@AKey)^);
   Result := TData(inherited GetKeyData(@AKey)^);
 end;
 end;
 
 
-function TFPGMap.KeyCompare(Key1, Key2: Pointer): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.KeyCompare(Key1, Key2: Pointer): Integer;
 begin
 begin
   if PKey(Key1)^ < PKey(Key2)^ then
   if PKey(Key1)^ < PKey(Key2)^ then
     Result := -1
     Result := -1
@@ -1335,7 +1335,7 @@ begin
     Result := 0;
     Result := 0;
 end;
 end;
 
 
-{function TFPGMap.DataCompare(Data1, Data2: Pointer): Integer;
+{function TFPGMap<TKey, TData>.DataCompare(Data1, Data2: Pointer): Integer;
 begin
 begin
   if PData(Data1)^ < PData(Data2)^ then
   if PData(Data1)^ < PData(Data2)^ then
     Result := -1
     Result := -1
@@ -1345,17 +1345,17 @@ begin
     Result := 0;
     Result := 0;
 end;}
 end;}
 
 
-function TFPGMap.KeyCustomCompare(Key1, Key2: Pointer): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.KeyCustomCompare(Key1, Key2: Pointer): Integer;
 begin
 begin
   Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
   Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
 end;
 end;
 
 
-function TFPGMap.DataCustomCompare(Data1, Data2: Pointer): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.DataCustomCompare(Data1, Data2: Pointer): Integer;
 begin
 begin
   Result := FOnDataCompare(TData(Data1^), TData(Data2^));
   Result := FOnDataCompare(TData(Data1^), TData(Data2^));
 end;
 end;
 
 
-procedure TFPGMap.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
 begin
 begin
   FOnKeyCompare := NewCompare;
   FOnKeyCompare := NewCompare;
   if NewCompare <> nil then
   if NewCompare <> nil then
@@ -1364,7 +1364,7 @@ begin
     OnKeyPtrCompare := @KeyCompare;
     OnKeyPtrCompare := @KeyCompare;
 end;
 end;
 
 
-procedure TFPGMap.SetOnDataCompare(NewCompare: TDataCompareFunc);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.SetOnDataCompare(NewCompare: TDataCompareFunc);
 begin
 begin
   FOnDataCompare := NewCompare;
   FOnDataCompare := NewCompare;
   if NewCompare <> nil then
   if NewCompare <> nil then
@@ -1373,64 +1373,64 @@ begin
     OnDataPtrCompare := nil;
     OnDataPtrCompare := nil;
 end;
 end;
 
 
-procedure TFPGMap.InitOnPtrCompare;
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.InitOnPtrCompare;
 begin
 begin
   SetOnKeyCompare(nil);
   SetOnKeyCompare(nil);
   SetOnDataCompare(nil);
   SetOnDataCompare(nil);
 end;
 end;
 
 
-procedure TFPGMap.PutKey(Index: Integer; const NewKey: TKey);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.PutKey(Index: Integer; const NewKey: TKey);
 begin
 begin
   inherited PutKey(Index, @NewKey);
   inherited PutKey(Index, @NewKey);
 end;
 end;
 
 
-procedure TFPGMap.PutData(Index: Integer; const NewData: TData);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.PutData(Index: Integer; const NewData: TData);
 begin
 begin
   inherited PutData(Index, @NewData);
   inherited PutData(Index, @NewData);
 end;
 end;
 
 
-procedure TFPGMap.PutKeyData(const AKey: TKey; const NewData: TData);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.PutKeyData(const AKey: TKey; const NewData: TData);
 begin
 begin
   inherited PutKeyData(@AKey, @NewData);
   inherited PutKeyData(@AKey, @NewData);
 end;
 end;
 
 
-function TFPGMap.Add(const AKey: TKey): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.Add(const AKey: TKey): Integer;
 begin
 begin
   Result := inherited Add(@AKey);
   Result := inherited Add(@AKey);
 end;
 end;
 
 
-function TFPGMap.Add(const AKey: TKey; const AData: TData): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.Add(const AKey: TKey; const AData: TData): Integer;
 begin
 begin
   Result := inherited Add(@AKey, @AData);
   Result := inherited Add(@AKey, @AData);
 end;
 end;
 
 
-function TFPGMap.Find(const AKey: TKey; out Index: Integer): Boolean;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.Find(const AKey: TKey; out Index: Integer): Boolean;
 begin
 begin
   Result := inherited Find(@AKey, Index);
   Result := inherited Find(@AKey, Index);
 end;
 end;
 
 
-function TFPGMap.IndexOf(const AKey: TKey): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.IndexOf(const AKey: TKey): Integer;
 begin
 begin
   Result := inherited IndexOf(@AKey);
   Result := inherited IndexOf(@AKey);
 end;
 end;
 
 
-function TFPGMap.IndexOfData(const AData: TData): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.IndexOfData(const AData: TData): Integer;
 begin
 begin
   { TODO: loop ? }
   { TODO: loop ? }
   Result := inherited IndexOfData(@AData);
   Result := inherited IndexOfData(@AData);
 end;
 end;
 
 
-procedure TFPGMap.InsertKey(Index: Integer; const AKey: TKey);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.InsertKey(Index: Integer; const AKey: TKey);
 begin
 begin
   inherited InsertKey(Index, @AKey);
   inherited InsertKey(Index, @AKey);
 end;
 end;
 
 
-procedure TFPGMap.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
+procedure TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
 begin
 begin
   inherited InsertKeyData(Index, @AKey, @AData);
   inherited InsertKeyData(Index, @AKey, @AData);
 end;
 end;
 
 
-function TFPGMap.Remove(const AKey: TKey): Integer;
+function TFPGMap{$ifndef OldSyntax}<TKey, TData>{$endif}.Remove(const AKey: TKey): Integer;
 begin
 begin
   Result := inherited Remove(@AKey);
   Result := inherited Remove(@AKey);
 end;
 end;
@@ -1439,23 +1439,23 @@ end;
                              TFPGMapInterfacedObjectData
                              TFPGMapInterfacedObjectData
  ****************************************************************************}
  ****************************************************************************}
 
 
-constructor TFPGMapInterfacedObjectData.Create;
+constructor TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.Create;
 begin
 begin
   inherited Create(SizeOf(TKey), SizeOf(TData));
   inherited Create(SizeOf(TKey), SizeOf(TData));
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.CopyItem(Src, Dest: Pointer);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.CopyItem(Src, Dest: Pointer);
 begin
 begin
   CopyKey(Src, Dest);
   CopyKey(Src, Dest);
   CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
   CopyData(PByte(Src)+KeySize, PByte(Dest)+KeySize);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.CopyKey(Src, Dest: Pointer);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.CopyKey(Src, Dest: Pointer);
 begin
 begin
   TKey(Dest^) := TKey(Src^);
   TKey(Dest^) := TKey(Src^);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.CopyData(Src, Dest: Pointer);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.CopyData(Src, Dest: Pointer);
 begin
 begin
   if Assigned(Pointer(Dest^)) then
   if Assigned(Pointer(Dest^)) then
     TData(Dest^)._Release;
     TData(Dest^)._Release;
@@ -1464,29 +1464,29 @@ begin
     TData(Dest^)._AddRef;
     TData(Dest^)._AddRef;
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.Deref(Item: Pointer);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.Deref(Item: Pointer);
 begin
 begin
   Finalize(TKey(Item^));
   Finalize(TKey(Item^));
   if Assigned(PPointer(PByte(Item)+KeySize)^) then
   if Assigned(PPointer(PByte(Item)+KeySize)^) then
     TData(Pointer(PByte(Item)+KeySize)^)._Release;
     TData(Pointer(PByte(Item)+KeySize)^)._Release;
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.GetKey(Index: Integer): TKey;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.GetKey(Index: Integer): TKey;
 begin
 begin
   Result := TKey(inherited GetKey(Index)^);
   Result := TKey(inherited GetKey(Index)^);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.GetData(Index: Integer): TData;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.GetData(Index: Integer): TData;
 begin
 begin
   Result := TData(inherited GetData(Index)^);
   Result := TData(inherited GetData(Index)^);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.GetKeyData(const AKey: TKey): TData;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.GetKeyData(const AKey: TKey): TData;
 begin
 begin
   Result := TData(inherited GetKeyData(@AKey)^);
   Result := TData(inherited GetKeyData(@AKey)^);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.KeyCompare(Key1, Key2: Pointer): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.KeyCompare(Key1, Key2: Pointer): Integer;
 begin
 begin
   if PKey(Key1)^ < PKey(Key2)^ then
   if PKey(Key1)^ < PKey(Key2)^ then
     Result := -1
     Result := -1
@@ -1496,7 +1496,7 @@ begin
     Result := 0;
     Result := 0;
 end;
 end;
 
 
-{function TFPGMapInterfacedObjectData.DataCompare(Data1, Data2: Pointer): Integer;
+{function TFPGMapInterfacedObjectData<TKey, TData>.DataCompare(Data1, Data2: Pointer): Integer;
 begin
 begin
   if PData(Data1)^ < PData(Data2)^ then
   if PData(Data1)^ < PData(Data2)^ then
     Result := -1
     Result := -1
@@ -1506,17 +1506,17 @@ begin
     Result := 0;
     Result := 0;
 end;}
 end;}
 
 
-function TFPGMapInterfacedObjectData.KeyCustomCompare(Key1, Key2: Pointer): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.KeyCustomCompare(Key1, Key2: Pointer): Integer;
 begin
 begin
   Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
   Result := FOnKeyCompare(TKey(Key1^), TKey(Key2^));
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.DataCustomCompare(Data1, Data2: Pointer): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.DataCustomCompare(Data1, Data2: Pointer): Integer;
 begin
 begin
   Result := FOnDataCompare(TData(Data1^), TData(Data2^));
   Result := FOnDataCompare(TData(Data1^), TData(Data2^));
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.SetOnKeyCompare(NewCompare: TKeyCompareFunc);
 begin
 begin
   FOnKeyCompare := NewCompare;
   FOnKeyCompare := NewCompare;
   if NewCompare <> nil then
   if NewCompare <> nil then
@@ -1525,7 +1525,7 @@ begin
     OnKeyPtrCompare := @KeyCompare;
     OnKeyPtrCompare := @KeyCompare;
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.SetOnDataCompare(NewCompare: TDataCompareFunc);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.SetOnDataCompare(NewCompare: TDataCompareFunc);
 begin
 begin
   FOnDataCompare := NewCompare;
   FOnDataCompare := NewCompare;
   if NewCompare <> nil then
   if NewCompare <> nil then
@@ -1534,64 +1534,64 @@ begin
     OnDataPtrCompare := nil;
     OnDataPtrCompare := nil;
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.InitOnPtrCompare;
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.InitOnPtrCompare;
 begin
 begin
   SetOnKeyCompare(nil);
   SetOnKeyCompare(nil);
   SetOnDataCompare(nil);
   SetOnDataCompare(nil);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.PutKey(Index: Integer; const NewKey: TKey);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.PutKey(Index: Integer; const NewKey: TKey);
 begin
 begin
   inherited PutKey(Index, @NewKey);
   inherited PutKey(Index, @NewKey);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.PutData(Index: Integer; const NewData: TData);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.PutData(Index: Integer; const NewData: TData);
 begin
 begin
   inherited PutData(Index, @NewData);
   inherited PutData(Index, @NewData);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.PutKeyData(const AKey: TKey; const NewData: TData);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.PutKeyData(const AKey: TKey; const NewData: TData);
 begin
 begin
   inherited PutKeyData(@AKey, @NewData);
   inherited PutKeyData(@AKey, @NewData);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.Add(const AKey: TKey): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.Add(const AKey: TKey): Integer;
 begin
 begin
   Result := inherited Add(@AKey);
   Result := inherited Add(@AKey);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.Add(const AKey: TKey; const AData: TData): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.Add(const AKey: TKey; const AData: TData): Integer;
 begin
 begin
   Result := inherited Add(@AKey, @AData);
   Result := inherited Add(@AKey, @AData);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.Find(const AKey: TKey; out Index: Integer): Boolean;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.Find(const AKey: TKey; out Index: Integer): Boolean;
 begin
 begin
   Result := inherited Find(@AKey, Index);
   Result := inherited Find(@AKey, Index);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.IndexOf(const AKey: TKey): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.IndexOf(const AKey: TKey): Integer;
 begin
 begin
   Result := inherited IndexOf(@AKey);
   Result := inherited IndexOf(@AKey);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.IndexOfData(const AData: TData): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.IndexOfData(const AData: TData): Integer;
 begin
 begin
   { TODO: loop ? }
   { TODO: loop ? }
   Result := inherited IndexOfData(@AData);
   Result := inherited IndexOfData(@AData);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.InsertKey(Index: Integer; const AKey: TKey);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.InsertKey(Index: Integer; const AKey: TKey);
 begin
 begin
   inherited InsertKey(Index, @AKey);
   inherited InsertKey(Index, @AKey);
 end;
 end;
 
 
-procedure TFPGMapInterfacedObjectData.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
+procedure TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.InsertKeyData(Index: Integer; const AKey: TKey; const AData: TData);
 begin
 begin
   inherited InsertKeyData(Index, @AKey, @AData);
   inherited InsertKeyData(Index, @AKey, @AData);
 end;
 end;
 
 
-function TFPGMapInterfacedObjectData.Remove(const AKey: TKey): Integer;
+function TFPGMapInterfacedObjectData{$ifndef OldSyntax}<TKey, TData>{$endif}.Remove(const AKey: TKey): Integer;
 begin
 begin
   Result := inherited Remove(@AKey);
   Result := inherited Remove(@AKey);
 end;
 end;

+ 4 - 4
tests/tbs/ub0569.pp

@@ -14,26 +14,26 @@ unit ub0569;
 
 
   implementation
   implementation
 
 
-    function TGen.getstring : string;
+    function TGen<T>.getstring : string;
       begin
       begin
         result:='Free Pascal';
         result:='Free Pascal';
       end;
       end;
 
 
 
 
-    function TGen.getwidestring : widestring;
+    function TGen<T>.getwidestring : widestring;
       begin
       begin
         { force widestring }
         { force widestring }
         result:='Free Pascal'#1234;
         result:='Free Pascal'#1234;
       end;
       end;
 
 
 
 
-    function TGen.getint : int64;
+    function TGen<T>.getint : int64;
       begin
       begin
         result:=1234123412341234;
         result:=1234123412341234;
       end;
       end;
 
 
 
 
-    function TGen.getreal : real;
+    function TGen<T>.getreal : real;
       begin
       begin
         result:=333.0;
         result:=333.0;
       end;
       end;

+ 1 - 1
tests/test/tgeneric1.pp

@@ -6,7 +6,7 @@ type
      procedure Add(item: _T);
      procedure Add(item: _T);
    end;
    end;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 begin
 begin
   data:=item;
   data:=item;
 end;
 end;

+ 2 - 2
tests/test/tgeneric11.pp

@@ -9,12 +9,12 @@ type
      procedure Assign(Source: specialize TList<_T>);
      procedure Assign(Source: specialize TList<_T>);
    end;
    end;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 begin
 begin
   data:=item;
   data:=item;
 end;
 end;
 
 
-procedure TList.Assign(Source: specialize TList<_T>);
+procedure TList<_T>.Assign(Source: specialize TList<_T>);
 begin
 begin
   data:=Source.data;
   data:=Source.data;
 end;
 end;

+ 2 - 2
tests/test/tgeneric12.pp

@@ -19,12 +19,12 @@ begin
   halt(1);
   halt(1);
 end;
 end;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 begin
 begin
   data:=item;
   data:=item;
 end;
 end;
 
 
-procedure TList.Test;
+procedure TList<_T>.Test;
 begin
 begin
   if data <> 10 then
   if data <> 10 then
     halt(1);
     halt(1);

+ 2 - 2
tests/test/tgeneric15.pp

@@ -47,12 +47,12 @@ end;
 
 
 { TStack }
 { TStack }
 
 
-procedure TStack.Clear;
+procedure TStack<T>.Clear;
 begin
 begin
   Writeln('old clear');
   Writeln('old clear');
 end;
 end;
 
 
-destructor TStack.Destroy;
+destructor TStack<T>.Destroy;
 begin
 begin
   Writeln('old destroy');
   Writeln('old destroy');
   Clear;
   Clear;

+ 3 - 3
tests/test/tgeneric16.pp

@@ -36,7 +36,7 @@ var
 
 
 { TAdvStack }
 { TAdvStack }
 
 
-procedure TAdvStack.Clear;
+procedure TAdvStack<T>.Clear;
 begin
 begin
   Writeln('new clear');
   Writeln('new clear');
   Idx:=Idx or 1;
   Idx:=Idx or 1;
@@ -52,12 +52,12 @@ end;
 
 
 { TStack }
 { TStack }
 
 
-procedure TStack.Clear;
+procedure TStack<T>.Clear;
 begin
 begin
   Writeln('old clear');
   Writeln('old clear');
 end;
 end;
 
 
-destructor TStack.Destroy;
+destructor TStack<T>.Destroy;
 begin
 begin
   Writeln('old destroy');
   Writeln('old destroy');
   Clear;
   Clear;

+ 3 - 3
tests/test/tgeneric17.pp

@@ -3,11 +3,11 @@
 type
 type
   generic TGListItem<T> = class(TObject)
   generic TGListItem<T> = class(TObject)
   public
   public
-    FNext: TGListItem;
-    procedure Assign(Source: TGListItem);
+    FNext: specialize TGListItem<T>;
+    procedure Assign(Source: specialize TGListItem<T>);
   end;
   end;
 
 
-procedure TGListItem.Assign(Source: TGListItem);
+procedure TGListItem<T>.Assign(Source: specialize TGListItem<T>);
 begin
 begin
   FNext := Source;
   FNext := Source;
 end;
 end;

+ 1 - 1
tests/test/tgeneric19.pp

@@ -6,7 +6,7 @@ type
 
 
   tc1 = specialize tc<string>;
   tc1 = specialize tc<string>;
 
 
-procedure tc.p(data : T);
+procedure tc<T>.p(data : T);
   begin
   begin
     readln(data);
     readln(data);
     writeln(data);
     writeln(data);

+ 1 - 1
tests/test/tgeneric2.pp

@@ -8,7 +8,7 @@ type
      procedure Add(item: _T);
      procedure Add(item: _T);
    end;
    end;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 var
 var
   i : integer;
   i : integer;
 begin
 begin

+ 1 - 1
tests/test/tgeneric20.pp

@@ -10,7 +10,7 @@ type
 
 
   tc1 = specialize tc<tr>;
   tc1 = specialize tc<tr>;
 
 
-procedure tc.p(data : T);
+procedure tc<T>.p(data : T);
   begin
   begin
     readln(data);
     readln(data);
     writeln(data);
     writeln(data);

+ 9 - 9
tests/test/tgeneric22.pp

@@ -4,33 +4,33 @@ type
   generic TGListItem<T> = class(TObject)
   generic TGListItem<T> = class(TObject)
   public var
   public var
     FValue: T;
     FValue: T;
-    FNext: TGListItem;
+    FNext: specialize TGListItem<T>;
     procedure SetValue(Value: T);
     procedure SetValue(Value: T);
     function GetValue: T;
     function GetValue: T;
-    procedure Assign(Source: TGListItem);
-    function Merge(Other: TGListItem): TGListItem;
+    procedure Assign(Source: specialize TGListItem<T>);
+    function Merge(Other: specialize TGListItem<T>): specialize TGListItem<T>;
   end;
   end;
 
 
-procedure TGListItem.SetValue(Value: T);
+procedure TGListItem<T>.SetValue(Value: T);
 begin
 begin
   FValue := Value;
   FValue := Value;
 end;
 end;
 
 
-function TGListItem.GetValue: T;
+function TGListItem<T>.GetValue: T;
 begin
 begin
   Result := FValue;
   Result := FValue;
 end;
 end;
 
 
-procedure TGListItem.Assign(Source: TGListItem);
+procedure TGListItem<T>.Assign(Source: specialize TGListItem<T>);
 begin
 begin
   FNext := Source;
   FNext := Source;
 end;
 end;
 
 
-function TGListItem.Merge(Other: TGListItem): TGListItem;
+function TGListItem<T>.Merge(Other: specialize TGListItem<T>): specialize TGListItem<T>;
 var
 var
-  Temp: TGListItem;
+  Temp: specialize TGListItem<T>;
 begin
 begin
-  Temp := TGListItem.Create;
+  Temp := specialize TGListItem<T>.Create;
   Temp.SetValue(FNext.GetValue + Other.FNext.GetValue);
   Temp.SetValue(FNext.GetValue + Other.FNext.GetValue);
   Result := Temp;
   Result := Temp;
 end;
 end;

+ 1 - 1
tests/test/tgeneric5.pp

@@ -12,7 +12,7 @@ type
 var
 var
   err : boolean;
   err : boolean;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 var
 var
   i : integer;
   i : integer;
   p : pointer;
   p : pointer;

+ 1 - 1
tests/test/tgeneric6.pp

@@ -13,7 +13,7 @@ type
      procedure Add(item: _T);
      procedure Add(item: _T);
    end;
    end;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 var
 var
   newitem : PListItem;
   newitem : PListItem;
 begin
 begin

+ 3 - 3
tests/test/tgeneric8.pp

@@ -17,7 +17,7 @@ type
      procedure Add(item: _T);
      procedure Add(item: _T);
    end;
    end;
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 var
 var
   newitem : PListItem;
   newitem : PListItem;
 begin
 begin
@@ -28,13 +28,13 @@ begin
 end;
 end;
 
 
 
 
-function TList.GetFirst : TIterator; inline;
+function TList<_T>.GetFirst : TIterator; inline;
   begin
   begin
     result:=first;
     result:=first;
   end;
   end;
 
 
 
 
-function TList.GetNext(i : TIterator) : TIterator; inline;
+function TList<_T>.GetNext(i : TIterator) : TIterator; inline;
   begin
   begin
     result:=i^.next;
     result:=i^.next;
   end;
   end;

+ 1 - 1
tests/test/tgeneric9.pp

@@ -7,7 +7,7 @@ type
     procedure Add(const AKey: TK; const AData: TD);
     procedure Add(const AKey: TK; const AData: TD);
   end;
   end;
 
 
-procedure TMap.Add(const AKey: TK; const AData: TD);
+procedure TMap<TK, TD>.Add(const AKey: TK; const AData: TD);
 begin
 begin
   Key := AKey;
   Key := AKey;
   Data := AData;
   Data := AData;

+ 2 - 2
tests/test/ugeneric10.pp

@@ -18,12 +18,12 @@ type
 
 
 implementation
 implementation
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 begin
 begin
   data:=item;
   data:=item;
 end;
 end;
 
 
-procedure TList.Sort(compare: TCompareFunc);
+procedure TList<_T>.Sort(compare: TCompareFunc);
 begin
 begin
   if compare(data, 20) <= 0 then
   if compare(data, 20) <= 0 then
     halt(1);
     halt(1);

+ 1 - 1
tests/test/ugeneric14.pp

@@ -19,7 +19,7 @@ begin
   Result := 1;
   Result := 1;
 end;
 end;
 
 
-procedure TGTest.DoSomething;
+procedure TGTest<T>.DoSomething;
 begin
 begin
   data := Foo;
   data := Foo;
 end;
 end;

+ 1 - 1
tests/test/ugeneric3.pp

@@ -12,7 +12,7 @@ type
 
 
 implementation
 implementation
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 begin
 begin
   data:=item;
   data:=item;
 end;
 end;

+ 1 - 1
tests/test/ugeneric4.pp

@@ -21,7 +21,7 @@ begin
 end;
 end;
 
 
 
 
-procedure TList.Fill;
+procedure TList<_T>.Fill;
 begin
 begin
   LocalFill;
   LocalFill;
   data:=globaldata;
   data:=globaldata;

+ 1 - 1
tests/test/ugeneric7.pp

@@ -13,7 +13,7 @@ unit ugeneric7;
   implementation
   implementation
 
 
 {$R-}
 {$R-}
-    procedure tgeneric.test;
+    procedure tgeneric<t>.test;
       var
       var
         l : longint;
         l : longint;
       begin
       begin

+ 6 - 6
tests/webtbs/tw10247.pp

@@ -28,33 +28,33 @@ type
     procedure SetV(v: TTNode.T);
     procedure SetV(v: TTNode.T);
   end;
   end;
 
 
-constructor TNode.Create;
+constructor TNode<T>.Create;
 begin
 begin
 end;
 end;
 
 
-destructor TNode.Destroy;
+destructor TNode<T>.Destroy;
 begin
 begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;
 
 
-constructor TContainer.Create;
+constructor TContainer<T>.Create;
 begin
 begin
   Data:=TTNode.Create;
   Data:=TTNode.Create;
 end;
 end;
 
 
-destructor TContainer.Destroy;
+destructor TContainer<T>.Destroy;
 begin
 begin
   Data.Free;
   Data.Free;
         inherited Destroy;
         inherited Destroy;
 end;
 end;
 
 
-function TContainer.GetAddr: TTNode.PT;
+function TContainer<T>.GetAddr: TTNode.PT;
 begin
 begin
         result := @Data.Data;
         result := @Data.Data;
 end;
 end;
 
 
 
 
-procedure TContainer.SetV(v: TTNode.T);
+procedure TContainer<T>.SetV(v: TTNode.T);
 begin
 begin
   Data.Data:=v;
   Data.Data:=v;
 end;
 end;

+ 2 - 2
tests/webtbs/tw10247b.pp

@@ -16,11 +16,11 @@ type
 
 
   TTNodeString = specialize TNode<String>;
   TTNodeString = specialize TNode<String>;
 
 
-constructor TNode.Create;
+constructor TNode<T>.Create;
 begin
 begin
 end;
 end;
 
 
-destructor TNode.Destroy;
+destructor TNode<T>.Destroy;
 begin
 begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;

+ 1 - 1
tests/webtbs/tw11435b.pp

@@ -12,7 +12,7 @@ type
 
 
 implementation
 implementation
 
 
-function gCBla.add( item: _T) : integer;
+function gCBla<_T>.add( item: _T) : integer;
 begin
 begin
   result := 0;
   result := 0;
 end;
 end;

+ 2 - 2
tests/webtbs/tw11435c.pp

@@ -21,12 +21,12 @@ type
 
 
 implementation
 implementation
 
 
-procedure TList.Add(item: _T);
+procedure TList<_T>.Add(item: _T);
 begin
 begin
   data:=item;
   data:=item;
 end;
 end;
 
 
-procedure TList.Sort(compare: TCompareFunc);
+procedure TList<_T>.Sort(compare: TCompareFunc);
 begin
 begin
   if compare(data, 20) <= 0 then
   if compare(data, 20) <= 0 then
     halt(1);
     halt(1);

+ 1 - 1
tests/webtbs/tw12249.pp

@@ -19,7 +19,7 @@ implementation
 
 
 { TG2 }
 { TG2 }
 
 
-destructor TG2.Destroy;
+destructor TG2<T>.Destroy;
 begin
 begin
   inherited Destroy;
   inherited Destroy;
 end;
 end;

+ 2 - 2
tests/webtbs/tw16065.pp

@@ -8,9 +8,9 @@ type
 
 
   TSpec = specialize TGen<Integer>;
   TSpec = specialize TGen<Integer>;
 
 
-function TGen.Check(ASource: TObject): Boolean;
+function TGen<_T>.Check(ASource: TObject): Boolean;
 begin
 begin
-  Result := (ASource is TGen)   // this line breaks the compiler...
+  Result := (ASource is specialize TGen<_T>)   // this line breaks the compiler...
   and (ASource is ClassType);   // ...it should be equivelent to this line
   and (ASource is ClassType);   // ...it should be equivelent to this line
 end;
 end;
 
 

+ 1 - 1
tests/webtbs/tw17193.pp

@@ -18,7 +18,7 @@ type
   
   
   S = specialize G2<Integer>;
   S = specialize G2<Integer>;
 
 
-procedure G2.P;
+procedure G2<T>.P;
 begin
 begin
 end;
 end;
 
 

+ 2 - 2
tests/webtbs/tw6624.pp

@@ -9,12 +9,12 @@ type
     function Two: T;
     function Two: T;
   end;
   end;
 
 
-procedure TGenTest1.One(const a: T);
+procedure TGenTest1<T>.One(const a: T);
 begin
 begin
 
 
 end;
 end;
 
 
-function TGenTest1.Two: T; // fails here
+function TGenTest1<T>.Two: T; // fails here
 begin
 begin
 end;
 end;
 
 

+ 1 - 1
tests/webtbs/tw9673.pp

@@ -12,7 +12,7 @@ type
   end;
   end;
 	    
 	    
 var
 var
-  b : Testclass.TList;
+  b : Testclass<T>.TList;
 	      
 	      
 	    
 	    
 implementation
 implementation

+ 1 - 1
tests/webtbs/tw9827.pp

@@ -8,7 +8,7 @@ type
     function some_func(): integer;
     function some_func(): integer;
   end;
   end;
 
 
-function GList.some_func(): integer;
+function GList<_T>.some_func(): integer;
 begin
 begin
   i := -1;
   i := -1;
   Result := -1;
   Result := -1;

+ 1 - 1
tests/webtbs/uw14124.pp

@@ -16,7 +16,7 @@ type
 
 
 implementation
 implementation
 
 
-procedure TGenericType.P;
+procedure TGenericType<TParamType>.P;
 begin
 begin
   F := FDefault; // <====== unit1.pas(21,16) Fatal: Internal error 200108121
   F := FDefault; // <====== unit1.pas(21,16) Fatal: Internal error 200108121
 end;
 end;

+ 1 - 1
tests/webtbs/uw15591.pp

@@ -14,7 +14,7 @@ type
 
 
 implementation
 implementation
 
 
-function GSmartArray.Length() :Integer;
+function GSmartArray<TSomeType>.Length() :Integer;
 begin
 begin
   Result := System.Length(fItems);
   Result := System.Length(fItems);
 end;
 end;