Преглед изворни кода

Merge branch 'unique-syms'

Conflicts:
	compiler/pdecl.pas
	compiler/pexpr.pas
	compiler/pgenutil.pas
	compiler/ptype.pas

The original log messages as git was a bit forgetting here :( (newest at the top):

commit 7ef252de8023494ee6d39910e289f9e31658d47b
Author: Sven Barth <pascaldragon@minerva>
Date:   Mon Nov 21 17:13:36 2011 +0100

    Fix the compilation of inline specializations of which the generic is derived from another generic.
    
    pgenutil.pas, generate_specialization:
    * Set the "block_type" to "bt_type" when parsing the type parameters, so that the nodes are returned as "ttypenode" instead of e.g. "tloadvmtaddrnode" in case of classes outside of type sections.
    * Set the "block_type" to "bt_type" before calling "read_name_type", so that no unexpected sideeffects happen, because types like classes normally only are declared inside type sections (e.g. for the case a generic class is derived from another generic class a classrefdef for the specialized parent class will be created inside the derived specialized class if the block type is not a type one).

commit 1041a8f7a3a41f4fdf2975ce40055c698281ce71
Author: Sven Barth <pascaldragon@minerva>
Date:   Fri Nov 18 19:03:50 2011 +0100

    Improve inline specializations a bit, so now expressions like "TSomeGeneric<TSomeType>.SomeClassProc OP SomeNonGeneric" is possible. Using another class function of a generic as the right side is not yet working (that still needs some thinking).
    
    To achive this the generalization code must basically continue directly after the "factor" call, so that the operator and the right side are correctly parsed when walking up the call stack. This is done by jumping from the end of the specialization code in the "<"-case to the start of "sub_expr". The freshly generated node (in the above example a callnode) will be passed down the callstack through a new parameter "factornode". If that is set (currently only in the case of a specialization on the left side) "factor" won't be called and the right side will be parsed with the "factornode" as the left side. If it is not set (which is the case for all other calls to "sub_expr" in the unit) then the usual call to "factor" will be done and the result will be used as the left side.

commit a01ccd265f8d6cc5a2f3e88e23afbcd3d5960afb
Author: Sven Barth <pascaldragon@minerva>
Date:   Fri Nov 18 18:37:04 2011 +0100

    Fix compilation of ppudump.
    
    symconst.pas:
    * Remove sto_has_generic, which was the last remainer of my "overloaded type symbols" approach.
    * Remove df_methods_specialized, as it isn't needed anymore with the recent "temporary symtable" solution.
    
    psub.pas, specialize_objectdefs, process_abstractrecorddef:
    Remove the checks for/inclusion of df_methods_specialized.
    
    utils/ppudump.pp:
    Add "sp_generic_dummy" to the symbol options.

commit d16deac060e65d4b53e8fe9c27fe7e1f6d00a416
Author: Sven Barth <pascaldragon@minerva>
Date:   Wed Nov 16 16:34:51 2011 +0100

    Fix compilation of "gset.pp" from fcl-stl.
    
    nld.pas:
    Extend ttypenode by a reference to the type symbol. Normally this is simply the typesym of the given def, but for specializations in type sections of generics this is not the case, because generate_specialization will return a reference to the generic definition and not the new one (thus the symbol will be wrong).
    
    ppu.pas:
    Increase PPU version because of the extension of ttypenode.
    
    pexpr.pas:
    * handle_factor_typenode: Extend the function by a "sym" parameter which will normally be "nil". In that case it is set to the def's typesym. The "typesym" field of the created type node is then set to this sym.
    * For now pass nearly always "nil" for the above mentioned sym except inside factor_read_id when we've encountered a typesym.
    
    ptype.pas, read_named_type, expr_type:
    Exchange the "is_owned_by" check with a "sym_is_owned_by" check so that we can correctly detect that we are using a specialized type declaration inside a generic (once nested generic are allowed this condition needs to be checked).

commit 23668d2fc9070afc26b4288ed0db9a8eaf6f40e6
Author: Sven Barth <pascaldragon@minerva>
Date:   Wed Nov 16 07:51:12 2011 +0100

    psub.pas:
    * tcgprocinfo.parse_body: Methods of generic classes need to set "parse_generic" as well, so that variables for "stacked generics" (generic array => generic record) inside the method body are handled correctly.
    * specialize_objectdefs: Don't try to generate method bodies for abstract methods.
    
    pdecvar.pas, read_property_dec:
    Allow specializations for the return types of properties (should they be allowed for index types as well?).
    
    symtable.pas:
    Add a new class "tspecializesymtable" which is basically a globalsymtable but is always assuming to be the current unit. This symtable is used in "generate_specializations" (see below) and is needed to allow visibilty checks for "private", etc. to succeed.
    
    pgenutil.pas, generate_specializations:
    Instead of hackily pushing a symtable that may contain conflicting symbols onto the symtable stack for the specialization, a temporary global symtable using the above mentioned "tspecializesymtable" is created and pushed. After the specialization is done all symbols and defs that were added to the temporary symtable are moved to their final symtable (either the global- or localsymtable of the unit, depending on the current position of compilation). This way symbols are correctly added to a top level symtable, but without potential side effects like resolving the wrong symbol.

git-svn-id: branches/svenbarth/generics@19671 -
svenbarth пре 13 година
родитељ
комит
594f84dc2c

+ 7 - 0
compiler/nld.pas

@@ -104,6 +104,8 @@ interface
           helperallowed : boolean;
           helperallowed : boolean;
           typedef : tdef;
           typedef : tdef;
           typedefderef : tderef;
           typedefderef : tderef;
+          typesym : tsym;
+          typesymderef : tderef;
           constructor create(def:tdef);virtual;
           constructor create(def:tdef);virtual;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
@@ -1034,6 +1036,7 @@ implementation
       begin
       begin
          inherited create(typen);
          inherited create(typen);
          typedef:=def;
          typedef:=def;
+         typesym:=def.typesym;
          allowed:=false;
          allowed:=false;
          helperallowed:=false;
          helperallowed:=false;
       end;
       end;
@@ -1043,6 +1046,7 @@ implementation
       begin
       begin
         inherited ppuload(t,ppufile);
         inherited ppuload(t,ppufile);
         ppufile.getderef(typedefderef);
         ppufile.getderef(typedefderef);
+        ppufile.getderef(typesymderef);
         allowed:=boolean(ppufile.getbyte);
         allowed:=boolean(ppufile.getbyte);
         helperallowed:=boolean(ppufile.getbyte);
         helperallowed:=boolean(ppufile.getbyte);
       end;
       end;
@@ -1052,6 +1056,7 @@ implementation
       begin
       begin
         inherited ppuwrite(ppufile);
         inherited ppuwrite(ppufile);
         ppufile.putderef(typedefderef);
         ppufile.putderef(typedefderef);
+        ppufile.putderef(typesymderef);
         ppufile.putbyte(byte(allowed));
         ppufile.putbyte(byte(allowed));
         ppufile.putbyte(byte(helperallowed));
         ppufile.putbyte(byte(helperallowed));
       end;
       end;
@@ -1061,6 +1066,7 @@ implementation
       begin
       begin
         inherited buildderefimpl;
         inherited buildderefimpl;
         typedefderef.build(typedef);
         typedefderef.build(typedef);
+        typesymderef.build(typesym);
       end;
       end;
 
 
 
 
@@ -1068,6 +1074,7 @@ implementation
       begin
       begin
         inherited derefimpl;
         inherited derefimpl;
         typedef:=tdef(typedefderef.resolve);
         typedef:=tdef(typedefderef.resolve);
+        typesym:=tsym(typesymderef.resolve);
       end;
       end;
 
 
 
 

+ 0 - 7
compiler/pdecl.pas

@@ -544,13 +544,6 @@ implementation
                     end;
                     end;
                 end;
                 end;
               { insert a new type if we don't reuse an existing symbol }
               { insert a new type if we don't reuse an existing symbol }
-              if not assigned(newtype) then
-                begin
-                  newtype:=ttypesym.create(genorgtypename,hdef);
-                  newtype.visibility:=symtablestack.top.currentvisibility;
-                  symtablestack.top.insert(newtype);
-                end;
-              { insert a newtype if we don't reuse an existing symbol }
               if not assigned(newtype) then
               if not assigned(newtype) then
                 begin
                 begin
                   newtype:=ttypesym.create(genorgtypename,hdef);
                   newtype:=ttypesym.create(genorgtypename,hdef);

+ 1 - 1
compiler/pdecvar.pas

@@ -448,7 +448,7 @@ implementation
          if (token=_COLON) or (paranr>0) or (astruct=nil) then
          if (token=_COLON) or (paranr>0) or (astruct=nil) then
            begin
            begin
               consume(_COLON);
               consume(_COLON);
-              single_type(p.propdef,[]);
+              single_type(p.propdef,[stoAllowSpecialization]);
 
 
               if is_dispinterface(astruct) and not is_automatable(p.propdef) then
               if is_dispinterface(astruct) and not is_automatable(p.propdef) then
                 Message1(type_e_not_automatable,p.propdef.typename);
                 Message1(type_e_not_automatable,p.propdef.typename);

+ 48 - 22
compiler/pexpr.pas

@@ -83,7 +83,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,typeonly:boolean;factornode:tnode):tnode;forward;
 
 
     const
     const
        { true, if the inherited call is anonymous }
        { true, if the inherited call is anonymous }
@@ -1289,11 +1289,13 @@ implementation
            end;
            end;
       end;
       end;
 
 
-    function handle_factor_typenode(hdef:tdef;getaddr:boolean;var again:boolean):tnode;
+    function handle_factor_typenode(hdef:tdef;getaddr:boolean;var again:boolean;sym:tsym):tnode;
       var
       var
         srsym : tsym;
         srsym : tsym;
         srsymtable : tsymtable;
         srsymtable : tsymtable;
       begin
       begin
+         if sym=nil then
+           sym:=hdef.typesym;
          if try_to_consume(_LKLAMMER) then
          if try_to_consume(_LKLAMMER) then
           begin
           begin
             result:=comp_expr(true,false);
             result:=comp_expr(true,false);
@@ -1317,6 +1319,7 @@ implementation
                 current_structdef.is_related(hdef) then
                 current_structdef.is_related(hdef) then
                begin
                begin
                  result:=ctypenode.create(hdef);
                  result:=ctypenode.create(hdef);
+                 ttypenode(result).typesym:=sym;
                  { search also in inherited methods }
                  { search also in inherited methods }
                  searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
                  searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
                  if assigned(srsym) then
                  if assigned(srsym) then
@@ -1330,6 +1333,7 @@ implementation
                     * @TObject.Load
                     * @TObject.Load
                     * static methods and variables }
                     * static methods and variables }
                 result:=ctypenode.create(hdef);
                 result:=ctypenode.create(hdef);
+                ttypenode(result).typesym:=sym;
                 { TP allows also @TMenu.Load if Load is only }
                 { TP allows also @TMenu.Load if Load is only }
                 { defined in an anchestor class              }
                 { defined in an anchestor class              }
                 srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
                 srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
@@ -1361,6 +1365,7 @@ implementation
                   { allows @Object.Method }
                   { allows @Object.Method }
                   { also allows static methods and variables }
                   { also allows static methods and variables }
                   result:=ctypenode.create(hdef);
                   result:=ctypenode.create(hdef);
+                  ttypenode(result).typesym:=sym;
                   { TP allows also @TMenu.Load if Load is only }
                   { TP allows also @TMenu.Load if Load is only }
                   { defined in an anchestor class              }
                   { defined in an anchestor class              }
                   srsym:=search_struct_member(tobjectdef(hdef),pattern);
                   srsym:=search_struct_member(tobjectdef(hdef),pattern);
@@ -1379,6 +1384,7 @@ implementation
                else
                else
                 begin
                 begin
                   result:=ctypenode.create(hdef);
                   result:=ctypenode.create(hdef);
+                  ttypenode(result).typesym:=sym;
                   { For a type block we simply return only
                   { For a type block we simply return only
                     the type. For all other blocks we return
                     the type. For all other blocks we return
                     a loadvmt node }
                     a loadvmt node }
@@ -1387,7 +1393,10 @@ implementation
                 end;
                 end;
              end
              end
             else
             else
-             result:=ctypenode.create(hdef);
+              begin
+                result:=ctypenode.create(hdef);
+                ttypenode(result).typesym:=sym;
+              end;
           end;
           end;
       end;
       end;
 
 
@@ -2140,7 +2149,7 @@ implementation
                        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;
-                       p1:=handle_factor_typenode(hdef,getaddr,again);
+                       p1:=handle_factor_typenode(hdef,getaddr,again,srsym);
                      end;
                      end;
                   end;
                   end;
 
 
@@ -2724,7 +2733,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,false,nil);
                       {  -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 }
@@ -2748,9 +2757,9 @@ implementation
                  else
                  else
                    begin
                    begin
                      if m_isolike_unary_minus in current_settings.modeswitches then
                      if m_isolike_unary_minus in current_settings.modeswitches then
-                       p1:=sub_expr(opmultiply,false,false)
+                       p1:=sub_expr(opmultiply,false,false,nil)
                      else
                      else
-                       p1:=sub_expr(oppower,false,false);
+                       p1:=sub_expr(oppower,false,false,nil);
 
 
                      p1:=cunaryminusnode.create(p1);
                      p1:=cunaryminusnode.create(p1);
                    end;
                    end;
@@ -2845,7 +2854,7 @@ implementation
           internalerror(2011053001);
           internalerror(2011053001);
         again:=false;
         again:=false;
         { handle potential typecasts, etc }
         { handle potential typecasts, etc }
-        p1:=handle_factor_typenode(def,false,again);
+        p1:=handle_factor_typenode(def,false,again,nil);
         { parse postfix operators }
         { parse postfix operators }
         if postfixoperators(p1,again,false) then
         if postfixoperators(p1,again,false) then
           if assigned(p1) and (p1.nodetype=typen) then
           if assigned(p1) and (p1.nodetype=typen) then
@@ -2866,7 +2875,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,typeonly:boolean;factornode:tnode):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.}
@@ -2914,6 +2923,8 @@ implementation
           result:=assigned(srsym);
           result:=assigned(srsym);
         end;
         end;
 
 
+      label
+        SubExprStart;
       var
       var
         p1,p2   : tnode;
         p1,p2   : tnode;
         oldt    : Ttoken;
         oldt    : Ttoken;
@@ -2922,10 +2933,16 @@ implementation
         gendef,parseddef : tdef;
         gendef,parseddef : tdef;
         gensym : tsym;
         gensym : tsym;
       begin
       begin
+        SubExprStart:
         if pred_level=highest_precedence then
         if pred_level=highest_precedence then
-          p1:=factor(false,typeonly)
+          begin
+            if factornode=nil then
+              p1:=factor(false,typeonly)
+            else
+              p1:=factornode;
+          end
         else
         else
-          p1:=sub_expr(succ(pred_level),true,typeonly);
+          p1:=sub_expr(succ(pred_level),true,typeonly,factornode);
         repeat
         repeat
           if (token in [NOTOKEN..last_operator]) and
           if (token in [NOTOKEN..last_operator]) and
              (token in operator_levels[pred_level]) and
              (token in operator_levels[pred_level]) and
@@ -2937,7 +2954,7 @@ implementation
              if pred_level=highest_precedence then
              if pred_level=highest_precedence then
                p2:=factor(false,false)
                p2:=factor(false,false)
              else
              else
-               p2:=sub_expr(succ(pred_level),true,typeonly);
+               p2:=sub_expr(succ(pred_level),true,typeonly,nil);
              case oldt of
              case oldt of
                _PLUS :
                _PLUS :
                  p1:=caddnode.create(addn,p1,p2);
                  p1:=caddnode.create(addn,p1,p2);
@@ -2990,13 +3007,19 @@ implementation
                          is always a classrefdef }
                          is always a classrefdef }
                        again:=false;
                        again:=false;
                        { handle potential typecasts, etc }
                        { handle potential typecasts, etc }
-                       p1:=handle_factor_typenode(gendef,false,again);
+                       p1:=handle_factor_typenode(gendef,false,again,nil);
                        { parse postfix operators }
                        { parse postfix operators }
                        if postfixoperators(p1,again,false) then
                        if postfixoperators(p1,again,false) then
                          if assigned(p1) then
                          if assigned(p1) then
                            p1.fileinfo:=filepos
                            p1.fileinfo:=filepos
                          else
                          else
                            p1:=cerrornode.create;
                            p1:=cerrornode.create;
+
+                       { with p1 now set we are in reality directly behind the
+                         call to "factor" thus we need to call down to that
+                         again }
+                       factornode:=p1;
+                       goto SubExprStart;
                      end
                      end
                    else
                    else
                      begin
                      begin
@@ -3069,13 +3092,16 @@ implementation
 
 
                        again:=false;
                        again:=false;
                        { handle potential typecasts, etc }
                        { handle potential typecasts, etc }
-                       p2:=handle_factor_typenode(gendef,false,again);
+                       p2:=handle_factor_typenode(gendef,false,again,nil);
                        { parse postfix operators }
                        { parse postfix operators }
                        if postfixoperators(p2,again,false) then
                        if postfixoperators(p2,again,false) then
                          if assigned(p2) then
                          if assigned(p2) then
                            p2.fileinfo:=filepos
                            p2.fileinfo:=filepos
                          else
                          else
                            p2:=cerrornode.create;
                            p2:=cerrornode.create;
+
+                       { here we don't need to call back down to "factor", thus
+                         no "goto" }
                      end;
                      end;
 
 
                    { now generate the "is" or "as" node }
                    { now generate the "is" or "as" node }
@@ -3135,7 +3161,7 @@ implementation
       begin
       begin
          oldafterassignment:=afterassignment;
          oldafterassignment:=afterassignment;
          afterassignment:=true;
          afterassignment:=true;
-         p1:=sub_expr(opcompare,accept_equal,typeonly);
+         p1:=sub_expr(opcompare,accept_equal,typeonly,nil);
          { 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);
@@ -3154,7 +3180,7 @@ implementation
 
 
       begin
       begin
          oldafterassignment:=afterassignment;
          oldafterassignment:=afterassignment;
-         p1:=sub_expr(opcompare,true,false);
+         p1:=sub_expr(opcompare,true,false,nil);
          { 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
@@ -3167,7 +3193,7 @@ implementation
            _POINTPOINT :
            _POINTPOINT :
              begin
              begin
                 consume(_POINTPOINT);
                 consume(_POINTPOINT);
-                p2:=sub_expr(opcompare,true,false);
+                p2:=sub_expr(opcompare,true,false,nil);
                 p1:=crangenode.create(p1,p2);
                 p1:=crangenode.create(p1,p2);
              end;
              end;
            _ASSIGNMENT :
            _ASSIGNMENT :
@@ -3175,7 +3201,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,false,nil);
                 if assigned(getprocvardef) then
                 if assigned(getprocvardef) then
                   handle_procvar(getprocvardef,p2);
                   handle_procvar(getprocvardef,p2);
                 getprocvardef:=nil;
                 getprocvardef:=nil;
@@ -3184,25 +3210,25 @@ implementation
            _PLUSASN :
            _PLUSASN :
              begin
              begin
                consume(_PLUSASN);
                consume(_PLUSASN);
-               p2:=sub_expr(opcompare,true,false);
+               p2:=sub_expr(opcompare,true,false,nil);
                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,false,nil);
                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,false,nil);
                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,false,nil);
                p1:=gen_c_style_operator(slashn,p1,p2);
                p1:=gen_c_style_operator(slashn,p1,p2);
             end;
             end;
           else
           else

+ 58 - 39
compiler/pgenutil.pas

@@ -42,14 +42,14 @@ uses
   { common }
   { common }
   cutils,
   cutils,
   { global }
   { global }
-  globals,tokens,verbose,
+  globals,globtype,tokens,verbose,
   { symtable }
   { symtable }
   symconst,symbase,symsym,symtable,
   symconst,symbase,symsym,symtable,
   { modules }
   { modules }
   fmodule,
   fmodule,
   { pass 1 }
   { pass 1 }
   htypechk,
   htypechk,
-  node,nobj,
+  node,nobj,nmem,
   { parser }
   { parser }
   scanner,
   scanner,
   pbase,pexpr,pdecsub,ptype;
   pbase,pexpr,pdecsub,ptype;
@@ -59,7 +59,7 @@ uses
       var
       var
         st  : TSymtable;
         st  : TSymtable;
         srsym : tsym;
         srsym : tsym;
-        pt2 : tnode;
+        pt2,pttmp : tnode;
         first,
         first,
         err : boolean;
         err : boolean;
         i,
         i,
@@ -77,9 +77,11 @@ uses
         vmtbuilder : TVMTBuilder;
         vmtbuilder : TVMTBuilder;
         onlyparsepara : boolean;
         onlyparsepara : boolean;
         specializest : tsymtable;
         specializest : tsymtable;
-        item: psymtablestackitem;
+        item : tobject;
         old_current_structdef : tabstractrecorddef;
         old_current_structdef : tabstractrecorddef;
         old_current_genericdef,old_current_specializedef : tstoreddef;
         old_current_genericdef,old_current_specializedef : tstoreddef;
+        tempst : tglobalsymtable;
+        old_block_type: tblock_type;
       begin
       begin
         { retrieve generic def that we are going to replace }
         { retrieve generic def that we are going to replace }
         genericdef:=tstoreddef(tt);
         genericdef:=tstoreddef(tt);
@@ -93,21 +95,9 @@ uses
             (genericdef.typesym.typ<>typesym)) then
             (genericdef.typesym.typ<>typesym)) then
            internalerror(2011042701);
            internalerror(2011042701);
 
 
-        { only need to record the tokens, then we don't know the type yet  ... }
-        if parse_generic then
-          begin
-            { ... but we have to insert a def into the symtable if the generic
-              is not a parent or an implemented interface else the deflist
-              of generic and specialization might not be equally sized which
-              is later assumed }
-            if not parse_class_parent then
-              tt:=tundefineddef.create;
-            onlyparsepara:=true;
-          end;
-
         { Only parse the parameters for recovery or
         { Only parse the parameters for recovery or
           for recording in genericbuf }
           for recording in genericbuf }
-        if onlyparsepara then
+        if parse_generic then
           begin
           begin
             consume(_LSHARPBRACKET);
             consume(_LSHARPBRACKET);
             gencount:=0;
             gencount:=0;
@@ -155,6 +145,10 @@ uses
 
 
         { Parse type parameters }
         { Parse type parameters }
         err:=false;
         err:=false;
+        { set the block type to type, so that the parsed type are returned as
+          ttypenode (e.g. classes are in non type-compatible blocks returned as
+          tloadvmtaddrnode) }
+        old_block_type:=block_type;
         { if parsedtype is set, then the first type identifer was already parsed
         { if parsedtype is set, then the first type identifer was already parsed
           (happens in inline specializations) and thus we only need to parse
           (happens in inline specializations) and thus we only need to parse
           the remaining types and do as if the first one was already given }
           the remaining types and do as if the first one was already given }
@@ -172,6 +166,7 @@ uses
               consume(_COMMA)
               consume(_COMMA)
             else
             else
               first:=false;
               first:=false;
+            block_type:=bt_type;
             pt2:=factor(false,true);
             pt2:=factor(false,true);
             if pt2.nodetype=typen then
             if pt2.nodetype=typen then
               begin
               begin
@@ -190,6 +185,7 @@ uses
               end;
               end;
             pt2.free;
             pt2.free;
           end;
           end;
+        block_type:=old_block_type;
 
 
         if err then
         if err then
           begin
           begin
@@ -273,10 +269,8 @@ uses
            (current_structdef.objname^=uspecializename) then
            (current_structdef.objname^=uspecializename) then
           tt:=current_structdef;
           tt:=current_structdef;
 
 
-        { for units specializations can already be needed in the interface, therefor we
-          will use the global symtable. Programs don't have a globalsymtable and there we
-          use the localsymtable }
-        if current_module.is_unit then
+        { decide in which symtable to put the specialization }
+        if current_module.is_unit and current_module.in_interface then
           specializest:=current_module.globalsymtable
           specializest:=current_module.globalsymtable
         else
         else
           specializest:=current_module.localsymtable;
           specializest:=current_module.localsymtable;
@@ -319,6 +313,7 @@ uses
             if assigned(hmodule.globalsymtable) then
             if assigned(hmodule.globalsymtable) then
               symtablestack.push(hmodule.globalsymtable);
               symtablestack.push(hmodule.globalsymtable);
 
 
+<<<<<<< HEAD
             { in case of a parent or an implemented interface the class needs
             { in case of a parent or an implemented interface the class needs
               to be inserted in the current unit and not in the class it's
               to be inserted in the current unit and not in the class it's
               used in }
               used in }
@@ -332,6 +327,18 @@ uses
                 if assigned(item) and (item^.symtable<>symtablestack.top) then
                 if assigned(item) and (item^.symtable<>symtablestack.top) then
                   symtablestack.push(item^.symtable);
                   symtablestack.push(item^.symtable);
               end;
               end;
+=======
+            { push the localsymtable if needed }
+            if (hmodule<>current_module) or not current_module.in_interface then
+              symtablestack.push(current_module.localsymtable);
+
+            { push a temporary global symtable so that the specialization is
+              added to the correct symtable; this symtable does not contain
+              any other symbols, so that the type resolution can not be
+              influenced by symbols in the current unit }
+            tempst:=tspecializesymtable.create(current_module.modulename^,current_module.moduleid);
+            symtablestack.push(tempst);
+>>>>>>> unique-syms
 
 
             { Reparse the original type definition }
             { Reparse the original type definition }
             if not err then
             if not err then
@@ -355,6 +362,14 @@ uses
                 srsym:=ttypesym.create(specializename,generrordef);
                 srsym:=ttypesym.create(specializename,generrordef);
                 specializest.insert(srsym);
                 specializest.insert(srsym);
 
 
+                { specializations are declarations as such it is the wised to
+                  declare set the blocktype to "type"; otherwise we'll
+                  experience unexpected side effects like the addition of
+                  classrefdefs if we have a generic that's derived from another
+                  generic }
+                old_block_type:=block_type;
+                block_type:=bt_type;
+
                 if not assigned(genericdef.generictokenbuf) then
                 if not assigned(genericdef.generictokenbuf) then
                   internalerror(200511171);
                   internalerror(200511171);
                 current_scanner.startreplaytokens(genericdef.generictokenbuf);
                 current_scanner.startreplaytokens(genericdef.generictokenbuf);
@@ -405,6 +420,10 @@ uses
                 { Consume the semicolon if it is also recorded }
                 { Consume the semicolon if it is also recorded }
                 try_to_consume(_SEMICOLON);
                 try_to_consume(_SEMICOLON);
 
 
+<<<<<<< HEAD
+=======
+                block_type:=old_block_type;
+>>>>>>> unique-syms
                 if parse_class_parent then
                 if parse_class_parent then
                   begin
                   begin
                     current_structdef:=old_current_structdef;
                     current_structdef:=old_current_structdef;
@@ -413,28 +432,29 @@ uses
                   end;
                   end;
               end;
               end;
 
 
+            { extract all created symbols and defs from the temporary symtable
+              and add them to the specializest }
+            for i:=0 to tempst.SymList.Count-1 do begin
+              item:=tempst.SymList.Items[i];
+              specializest.SymList.Add(tempst.SymList.NameOfIndex(i),item);
+              tsym(item).Owner:=specializest;
+              tempst.SymList.Extract(item);
+            end;
+
+            for i:=0 to tempst.DefList.Count-1 do begin
+              item:=tempst.DefList.Items[i];
+              specializest.DefList.Add(item);
+              tdef(item).owner:=specializest;
+              tempst.DefList.Extract(item);
+            end;
+
+            tempst.free;
+
             { Restore symtablestack }
             { Restore symtablestack }
             current_module.extendeddefs.free;
             current_module.extendeddefs.free;
             current_module.extendeddefs:=oldextendeddefs;
             current_module.extendeddefs:=oldextendeddefs;
             symtablestack.free;
             symtablestack.free;
             symtablestack:=oldsymtablestack;
             symtablestack:=oldsymtablestack;
-          end
-        else
-          begin
-            { There is comment few lines before ie 200512115
-              saying "We are parsing the same objectdef, the def index numbers
-              are the same". This is wrong (index numbers are not same)
-              in case there is specialization (S2 in this case) inside
-              specialized generic (G2 in this case) which is equal to
-              some previous specialization (S1 in this case). In that case,
-              new symbol is not added to currently specialized type
-              (S in this case) for that specializations (S2 in this case),
-              and this results in that specialization and generic definition
-              don't have same number of elements in their object symbol tables.
-              This patch adds undefined def to ensure that those
-              two symbol tables will have same number of elements.
-            }
-            tundefineddef.create;
           end;
           end;
 
 
         if not (token in [_GT, _RSHARPBRACKET]) then
         if not (token in [_GT, _RSHARPBRACKET]) then
@@ -502,5 +522,4 @@ uses
           end;
           end;
        end;
        end;
 
 
-
 end.
 end.

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 {$endif Test_Double_checksum}
 
 
 const
 const
-  CurrentPPUVersion = 131;
+  CurrentPPUVersion = 132;
 
 
 { buffer sizes }
 { buffer sizes }
   maxentrysize = 1024;
   maxentrysize = 1024;

+ 10 - 1
compiler/psub.pas

@@ -1389,17 +1389,22 @@ implementation
          old_current_structdef: tabstractrecorddef;
          old_current_structdef: tabstractrecorddef;
          old_current_genericdef,
          old_current_genericdef,
          old_current_specializedef: tstoreddef;
          old_current_specializedef: tstoreddef;
+         old_parse_generic: boolean;
       begin
       begin
          old_current_procinfo:=current_procinfo;
          old_current_procinfo:=current_procinfo;
          old_block_type:=block_type;
          old_block_type:=block_type;
          old_current_structdef:=current_structdef;
          old_current_structdef:=current_structdef;
          old_current_genericdef:=current_genericdef;
          old_current_genericdef:=current_genericdef;
          old_current_specializedef:=current_specializedef;
          old_current_specializedef:=current_specializedef;
+         old_parse_generic:=parse_generic;
 
 
          current_procinfo:=self;
          current_procinfo:=self;
          current_structdef:=procdef.struct;
          current_structdef:=procdef.struct;
          if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
          if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
-           current_genericdef:=current_structdef;
+           begin
+             current_genericdef:=current_structdef;
+             parse_generic:=true;
+           end;
          if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
          if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
            current_specializedef:=current_structdef;
            current_specializedef:=current_structdef;
 
 
@@ -1511,6 +1516,7 @@ implementation
          current_genericdef:=old_current_genericdef;
          current_genericdef:=old_current_genericdef;
          current_specializedef:=old_current_specializedef;
          current_specializedef:=old_current_specializedef;
          current_procinfo:=old_current_procinfo;
          current_procinfo:=old_current_procinfo;
+         parse_generic:=old_parse_generic;
 
 
          { Restore old state }
          { Restore old state }
          block_type:=old_block_type;
          block_type:=old_block_type;
@@ -2005,6 +2011,9 @@ implementation
               hp:=tdef(def.symtable.DefList[i]);
               hp:=tdef(def.symtable.DefList[i]);
               if hp.typ=procdef then
               if hp.typ=procdef then
                begin
                begin
+                 { only generate the code if we need a body }
+                 if assigned(tprocdef(hp).struct) and not tprocdef(hp).forwarddef then
+                   continue;
                  if assigned(tprocdef(hp).genericdef) and
                  if assigned(tprocdef(hp).genericdef) and
                    (tprocdef(hp).genericdef.typ=procdef) and
                    (tprocdef(hp).genericdef.typ=procdef) and
                    assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then
                    assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then

+ 2 - 1
compiler/ptype.pas

@@ -871,7 +871,8 @@ implementation
                                parse_generic and
                                parse_generic and
                                (current_genericdef.typ in [recorddef,objectdef]) and
                                (current_genericdef.typ in [recorddef,objectdef]) and
                                (def.typ in [recorddef,objectdef]) and
                                (def.typ in [recorddef,objectdef]) and
-                               is_owned_by(def,tabstractrecorddef(current_genericdef))
+                               (ttypenode(pt1).typesym<>nil) and
+                               sym_is_owned_by(ttypenode(pt1).typesym,tabstractrecorddef(current_genericdef).symtable)
                              )
                              )
                            then
                            then
                          begin
                          begin

+ 1 - 3
compiler/symconst.pas

@@ -479,9 +479,7 @@ type
 
 
   { options for symtables }
   { options for symtables }
   tsymtableoption = (
   tsymtableoption = (
-    sto_has_helper,        { contains at least one helper symbol }
-    sto_has_generic        { contains at least one symbol that is overloaded
-                             with generic defs }
+    sto_has_helper        { contains at least one helper symbol }
   );
   );
   tsymtableoptions = set of tsymtableoption;
   tsymtableoptions = set of tsymtableoption;
 
 

+ 15 - 1
compiler/symtable.pas

@@ -161,6 +161,11 @@ interface
           function  checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
           function  checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override;
        end;
        end;
 
 
+       tspecializesymtable = class(tglobalsymtable)
+       public
+          function iscurrentunit:boolean;override;
+       end;
+
        twithsymtable = class(TSymtable)
        twithsymtable = class(TSymtable)
           withrefnode : tobject; { tnode }
           withrefnode : tobject; { tnode }
           constructor create(aowner:tdef;ASymList:TFPHashObjectList;refnode:tobject{tnode});
           constructor create(aowner:tdef;ASymList:TFPHashObjectList;refnode:tobject{tnode});
@@ -343,7 +348,6 @@ implementation
     var
     var
       dupnr : longint; { unique number for duplicate symbols }
       dupnr : longint; { unique number for duplicate symbols }
 
 
-
 {*****************************************************************************
 {*****************************************************************************
                              TStoredSymtable
                              TStoredSymtable
 *****************************************************************************}
 *****************************************************************************}
@@ -1555,6 +1559,16 @@ implementation
       end;
       end;
 
 
 
 
+{*****************************************************************************
+                             tspecializesymtable
+*****************************************************************************}
+
+    function tspecializesymtable.iscurrentunit: boolean;
+      begin
+        Result := true;
+      end;
+
+
 {****************************************************************************
 {****************************************************************************
                               TWITHSYMTABLE
                               TWITHSYMTABLE
 ****************************************************************************}
 ****************************************************************************}

+ 2 - 1
compiler/utils/ppudump.pp

@@ -794,7 +794,8 @@ const
      (mask:sp_internal;           str:'Internal'),
      (mask:sp_internal;           str:'Internal'),
      (mask:sp_implicitrename;     str:'Implicit Rename'),
      (mask:sp_implicitrename;     str:'Implicit Rename'),
      (mask:sp_generic_para;       str:'Generic Parameter'),
      (mask:sp_generic_para;       str:'Generic Parameter'),
-     (mask:sp_has_deprecated_msg; str:'Has Deprecated Message')
+     (mask:sp_has_deprecated_msg; str:'Has Deprecated Message'),
+     (mask:sp_generic_dummy;      str:'Generic Dummy')
   );
   );
 var
 var
   symoptions : tsymoptions;
   symoptions : tsymoptions;