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 -
This commit is contained in:
svenbarth 2011-11-23 17:25:09 +00:00
parent 3dcefeb20b
commit 594f84dc2c
11 changed files with 145 additions and 77 deletions

View File

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

View File

@ -544,13 +544,6 @@ implementation
end;
end;
{ 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
begin
newtype:=ttypesym.create(genorgtypename,hdef);

View File

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

View File

@ -83,7 +83,7 @@ implementation
const
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
{ true, if the inherited call is anonymous }
@ -1289,11 +1289,13 @@ implementation
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
srsym : tsym;
srsymtable : tsymtable;
begin
if sym=nil then
sym:=hdef.typesym;
if try_to_consume(_LKLAMMER) then
begin
result:=comp_expr(true,false);
@ -1317,6 +1319,7 @@ implementation
current_structdef.is_related(hdef) then
begin
result:=ctypenode.create(hdef);
ttypenode(result).typesym:=sym;
{ search also in inherited methods }
searchsym_in_class(tobjectdef(hdef),tobjectdef(current_structdef),pattern,srsym,srsymtable,true);
if assigned(srsym) then
@ -1330,6 +1333,7 @@ implementation
* @TObject.Load
* static methods and variables }
result:=ctypenode.create(hdef);
ttypenode(result).typesym:=sym;
{ TP allows also @TMenu.Load if Load is only }
{ defined in an anchestor class }
srsym:=search_struct_member(tabstractrecorddef(hdef),pattern);
@ -1361,6 +1365,7 @@ implementation
{ allows @Object.Method }
{ also allows static methods and variables }
result:=ctypenode.create(hdef);
ttypenode(result).typesym:=sym;
{ TP allows also @TMenu.Load if Load is only }
{ defined in an anchestor class }
srsym:=search_struct_member(tobjectdef(hdef),pattern);
@ -1379,6 +1384,7 @@ implementation
else
begin
result:=ctypenode.create(hdef);
ttypenode(result).typesym:=sym;
{ For a type block we simply return only
the type. For all other blocks we return
a loadvmt node }
@ -1387,7 +1393,10 @@ implementation
end;
end
else
result:=ctypenode.create(hdef);
begin
result:=ctypenode.create(hdef);
ttypenode(result).typesym:=sym;
end;
end;
end;
@ -2140,7 +2149,7 @@ implementation
if (hdef=cvarianttype) and
not(cs_compilesystem in current_settings.moduleswitches) then
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;
@ -2724,7 +2733,7 @@ implementation
{ ugly hack, but necessary to be able to parse }
{ -9223372036854775808 as int64 (JM) }
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
This was the reason of tw0869.pp test failure PM }
@ -2748,9 +2757,9 @@ implementation
else
begin
if m_isolike_unary_minus in current_settings.modeswitches then
p1:=sub_expr(opmultiply,false,false)
p1:=sub_expr(opmultiply,false,false,nil)
else
p1:=sub_expr(oppower,false,false);
p1:=sub_expr(oppower,false,false,nil);
p1:=cunaryminusnode.create(p1);
end;
@ -2845,7 +2854,7 @@ implementation
internalerror(2011053001);
again:=false;
{ handle potential typecasts, etc }
p1:=handle_factor_typenode(def,false,again);
p1:=handle_factor_typenode(def,false,again,nil);
{ parse postfix operators }
if postfixoperators(p1,again,false) 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],
[_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
level, or any higher level. Replaces the old term, simpl_expr and
simpl2_expr.}
@ -2914,6 +2923,8 @@ implementation
result:=assigned(srsym);
end;
label
SubExprStart;
var
p1,p2 : tnode;
oldt : Ttoken;
@ -2922,10 +2933,16 @@ implementation
gendef,parseddef : tdef;
gensym : tsym;
begin
SubExprStart:
if pred_level=highest_precedence then
p1:=factor(false,typeonly)
begin
if factornode=nil then
p1:=factor(false,typeonly)
else
p1:=factornode;
end
else
p1:=sub_expr(succ(pred_level),true,typeonly);
p1:=sub_expr(succ(pred_level),true,typeonly,factornode);
repeat
if (token in [NOTOKEN..last_operator]) and
(token in operator_levels[pred_level]) and
@ -2937,7 +2954,7 @@ implementation
if pred_level=highest_precedence then
p2:=factor(false,false)
else
p2:=sub_expr(succ(pred_level),true,typeonly);
p2:=sub_expr(succ(pred_level),true,typeonly,nil);
case oldt of
_PLUS :
p1:=caddnode.create(addn,p1,p2);
@ -2990,13 +3007,19 @@ implementation
is always a classrefdef }
again:=false;
{ handle potential typecasts, etc }
p1:=handle_factor_typenode(gendef,false,again);
p1:=handle_factor_typenode(gendef,false,again,nil);
{ parse postfix operators }
if postfixoperators(p1,again,false) then
if assigned(p1) then
p1.fileinfo:=filepos
else
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
else
begin
@ -3069,13 +3092,16 @@ implementation
again:=false;
{ handle potential typecasts, etc }
p2:=handle_factor_typenode(gendef,false,again);
p2:=handle_factor_typenode(gendef,false,again,nil);
{ parse postfix operators }
if postfixoperators(p2,again,false) then
if assigned(p2) then
p2.fileinfo:=filepos
else
p2:=cerrornode.create;
{ here we don't need to call back down to "factor", thus
no "goto" }
end;
{ now generate the "is" or "as" node }
@ -3135,7 +3161,7 @@ implementation
begin
oldafterassignment:=afterassignment;
afterassignment:=true;
p1:=sub_expr(opcompare,accept_equal,typeonly);
p1:=sub_expr(opcompare,accept_equal,typeonly,nil);
{ get the resultdef for this expression }
if not assigned(p1.resultdef) then
do_typecheckpass(p1);
@ -3154,7 +3180,7 @@ implementation
begin
oldafterassignment:=afterassignment;
p1:=sub_expr(opcompare,true,false);
p1:=sub_expr(opcompare,true,false,nil);
{ get the resultdef for this expression }
if not assigned(p1.resultdef) and
dotypecheck then
@ -3167,7 +3193,7 @@ implementation
_POINTPOINT :
begin
consume(_POINTPOINT);
p2:=sub_expr(opcompare,true,false);
p2:=sub_expr(opcompare,true,false,nil);
p1:=crangenode.create(p1,p2);
end;
_ASSIGNMENT :
@ -3175,7 +3201,7 @@ implementation
consume(_ASSIGNMENT);
if (p1.resultdef.typ=procvardef) then
getprocvardef:=tprocvardef(p1.resultdef);
p2:=sub_expr(opcompare,true,false);
p2:=sub_expr(opcompare,true,false,nil);
if assigned(getprocvardef) then
handle_procvar(getprocvardef,p2);
getprocvardef:=nil;
@ -3184,25 +3210,25 @@ implementation
_PLUSASN :
begin
consume(_PLUSASN);
p2:=sub_expr(opcompare,true,false);
p2:=sub_expr(opcompare,true,false,nil);
p1:=gen_c_style_operator(addn,p1,p2);
end;
_MINUSASN :
begin
consume(_MINUSASN);
p2:=sub_expr(opcompare,true,false);
p2:=sub_expr(opcompare,true,false,nil);
p1:=gen_c_style_operator(subn,p1,p2);
end;
_STARASN :
begin
consume(_STARASN );
p2:=sub_expr(opcompare,true,false);
p2:=sub_expr(opcompare,true,false,nil);
p1:=gen_c_style_operator(muln,p1,p2);
end;
_SLASHASN :
begin
consume(_SLASHASN );
p2:=sub_expr(opcompare,true,false);
p2:=sub_expr(opcompare,true,false,nil);
p1:=gen_c_style_operator(slashn,p1,p2);
end;
else

View File

@ -42,14 +42,14 @@ uses
{ common }
cutils,
{ global }
globals,tokens,verbose,
globals,globtype,tokens,verbose,
{ symtable }
symconst,symbase,symsym,symtable,
{ modules }
fmodule,
{ pass 1 }
htypechk,
node,nobj,
node,nobj,nmem,
{ parser }
scanner,
pbase,pexpr,pdecsub,ptype;
@ -59,7 +59,7 @@ uses
var
st : TSymtable;
srsym : tsym;
pt2 : tnode;
pt2,pttmp : tnode;
first,
err : boolean;
i,
@ -77,9 +77,11 @@ uses
vmtbuilder : TVMTBuilder;
onlyparsepara : boolean;
specializest : tsymtable;
item: psymtablestackitem;
item : tobject;
old_current_structdef : tabstractrecorddef;
old_current_genericdef,old_current_specializedef : tstoreddef;
tempst : tglobalsymtable;
old_block_type: tblock_type;
begin
{ retrieve generic def that we are going to replace }
genericdef:=tstoreddef(tt);
@ -93,21 +95,9 @@ uses
(genericdef.typesym.typ<>typesym)) then
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
for recording in genericbuf }
if onlyparsepara then
if parse_generic then
begin
consume(_LSHARPBRACKET);
gencount:=0;
@ -155,6 +145,10 @@ uses
{ Parse type parameters }
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
(happens in inline specializations) and thus we only need to parse
the remaining types and do as if the first one was already given }
@ -172,6 +166,7 @@ uses
consume(_COMMA)
else
first:=false;
block_type:=bt_type;
pt2:=factor(false,true);
if pt2.nodetype=typen then
begin
@ -190,6 +185,7 @@ uses
end;
pt2.free;
end;
block_type:=old_block_type;
if err then
begin
@ -273,10 +269,8 @@ uses
(current_structdef.objname^=uspecializename) then
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
else
specializest:=current_module.localsymtable;
@ -319,6 +313,7 @@ uses
if assigned(hmodule.globalsymtable) then
symtablestack.push(hmodule.globalsymtable);
<<<<<<< HEAD
{ 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
used in }
@ -332,6 +327,18 @@ uses
if assigned(item) and (item^.symtable<>symtablestack.top) then
symtablestack.push(item^.symtable);
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 }
if not err then
@ -355,6 +362,14 @@ uses
srsym:=ttypesym.create(specializename,generrordef);
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
internalerror(200511171);
current_scanner.startreplaytokens(genericdef.generictokenbuf);
@ -405,6 +420,10 @@ uses
{ Consume the semicolon if it is also recorded }
try_to_consume(_SEMICOLON);
<<<<<<< HEAD
=======
block_type:=old_block_type;
>>>>>>> unique-syms
if parse_class_parent then
begin
current_structdef:=old_current_structdef;
@ -413,28 +432,29 @@ uses
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 }
current_module.extendeddefs.free;
current_module.extendeddefs:=oldextendeddefs;
symtablestack.free;
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;
if not (token in [_GT, _RSHARPBRACKET]) then
@ -502,5 +522,4 @@ uses
end;
end;
end.

View File

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

View File

@ -1389,17 +1389,22 @@ implementation
old_current_structdef: tabstractrecorddef;
old_current_genericdef,
old_current_specializedef: tstoreddef;
old_parse_generic: boolean;
begin
old_current_procinfo:=current_procinfo;
old_block_type:=block_type;
old_current_structdef:=current_structdef;
old_current_genericdef:=current_genericdef;
old_current_specializedef:=current_specializedef;
old_parse_generic:=parse_generic;
current_procinfo:=self;
current_structdef:=procdef.struct;
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
current_specializedef:=current_structdef;
@ -1511,6 +1516,7 @@ implementation
current_genericdef:=old_current_genericdef;
current_specializedef:=old_current_specializedef;
current_procinfo:=old_current_procinfo;
parse_generic:=old_parse_generic;
{ Restore old state }
block_type:=old_block_type;
@ -2005,6 +2011,9 @@ implementation
hp:=tdef(def.symtable.DefList[i]);
if hp.typ=procdef then
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
(tprocdef(hp).genericdef.typ=procdef) and
assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then

View File

@ -871,7 +871,8 @@ implementation
parse_generic and
(current_genericdef.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
begin

View File

@ -479,9 +479,7 @@ type
{ options for symtables }
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;

View File

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

View File

@ -794,7 +794,8 @@ const
(mask:sp_internal; str:'Internal'),
(mask:sp_implicitrename; str:'Implicit Rename'),
(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
symoptions : tsymoptions;