|
@@ -220,17 +220,24 @@ interface
|
|
|
function searchsym_type(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;
|
|
|
function searchsym_in_named_module(const unitname, symname: TIDString; out srsym: tsym; out srsymtable: tsymtable): boolean;
|
|
|
- function searchsym_in_class(classh,contextclassh:tobjectdef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
|
|
|
+ function searchsym_in_class(classh,contextclassh:tobjectdef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;searchhelper:boolean):boolean;
|
|
|
function searchsym_in_record(recordh:tabstractrecorddef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
|
|
|
function searchsym_in_class_by_msgint(classh:tobjectdef;msgid:longint;out srdef : tdef;out srsym:tsym;out srsymtable:TSymtable):boolean;
|
|
|
function searchsym_in_class_by_msgstr(classh:tobjectdef;const s:string;out srsym:tsym;out srsymtable:TSymtable):boolean;
|
|
|
+ { searches symbols inside of a helper's implementation }
|
|
|
+ function searchsym_in_helper(classh,contextclassh:tobjectdef;const s: TIDString;out srsym:tsym;out srsymtable:TSymtable;aHasInherited:boolean):boolean;
|
|
|
function search_system_type(const s: TIDString): ttypesym;
|
|
|
function try_search_system_type(const s: TIDString): ttypesym;
|
|
|
function search_named_unit_globaltype(const unitname, typename: TIDString; throwerror: boolean): ttypesym;
|
|
|
function search_struct_member(pd : tabstractrecorddef;const s : string):tsym;
|
|
|
function search_assignment_operator(from_def,to_def:Tdef;explicit:boolean):Tprocdef;
|
|
|
function search_enumerator_operator(from_def,to_def:Tdef):Tprocdef;
|
|
|
- function search_class_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
+ { searches for the helper definition that's currently active for pd }
|
|
|
+ function search_last_objectpascal_helper(pd,contextclassh : tabstractrecorddef;out odef : tobjectdef):boolean;
|
|
|
+ { searches whether the symbol s is available in the currently active }
|
|
|
+ { helper for pd }
|
|
|
+ function search_objectpascal_helper(pd,contextclassh : tabstractrecorddef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
+ function search_objc_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
function search_objc_method(const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
{Looks for macro s (must be given in upper case) in the macrosymbolstack, }
|
|
|
{and returns it if found. Returns nil otherwise.}
|
|
@@ -349,6 +356,11 @@ implementation
|
|
|
|
|
|
procedure tstoredsymtable.ppuload(ppufile:tcompilerppufile);
|
|
|
begin
|
|
|
+ { load the table's flags }
|
|
|
+ if ppufile.readentry<>ibsymtableoptions then
|
|
|
+ Message(unit_f_ppu_read_error);
|
|
|
+ ppufile.getsmallset(tableoptions);
|
|
|
+
|
|
|
{ load definitions }
|
|
|
loaddefs(ppufile);
|
|
|
|
|
@@ -359,6 +371,10 @@ implementation
|
|
|
|
|
|
procedure tstoredsymtable.ppuwrite(ppufile:tcompilerppufile);
|
|
|
begin
|
|
|
+ { write the table's flags }
|
|
|
+ ppufile.putsmallset(tableoptions);
|
|
|
+ ppufile.writeentry(ibsymtableoptions);
|
|
|
+
|
|
|
{ write definitions }
|
|
|
writedefs(ppufile);
|
|
|
|
|
@@ -1269,10 +1285,7 @@ implementation
|
|
|
oldtyp:=ppufile.entrytyp;
|
|
|
ppufile.entrytyp:=subentryid;
|
|
|
|
|
|
- { write definitions }
|
|
|
- writedefs(ppufile);
|
|
|
- { write symbols }
|
|
|
- writesyms(ppufile);
|
|
|
+ inherited ppuwrite(ppufile);
|
|
|
|
|
|
ppufile.entrytyp:=oldtyp;
|
|
|
end;
|
|
@@ -1811,9 +1824,16 @@ implementation
|
|
|
end;
|
|
|
vis_strictprotected :
|
|
|
begin
|
|
|
- result:=assigned(current_structdef) and
|
|
|
- (current_structdef.is_related(symownerdef) or
|
|
|
- is_owned_by(current_structdef,symownerdef));
|
|
|
+ result:=(
|
|
|
+ assigned(current_structdef) and
|
|
|
+ (current_structdef.is_related(symownerdef) or
|
|
|
+ is_owned_by(current_structdef,symownerdef))
|
|
|
+ ) or
|
|
|
+ (
|
|
|
+ { helpers can access strict protected symbols }
|
|
|
+ is_objectpascal_helper(contextobjdef) and
|
|
|
+ tobjectdef(contextobjdef).extendeddef.is_related(symownerdef)
|
|
|
+ );
|
|
|
end;
|
|
|
vis_protected :
|
|
|
begin
|
|
@@ -1843,7 +1863,12 @@ implementation
|
|
|
(
|
|
|
not assigned(current_structdef) and
|
|
|
(symownerdef.owner.iscurrentunit)
|
|
|
- )
|
|
|
+ ) or
|
|
|
+ (
|
|
|
+ { helpers can access protected symbols }
|
|
|
+ is_objectpascal_helper(contextobjdef) and
|
|
|
+ tobjectdef(contextobjdef).extendeddef.is_related(symownerdef)
|
|
|
+ )
|
|
|
)
|
|
|
);
|
|
|
end;
|
|
@@ -1899,7 +1924,7 @@ implementation
|
|
|
srsymtable:=stackitem^.symtable;
|
|
|
if (srsymtable.symtabletype=objectsymtable) then
|
|
|
begin
|
|
|
- if searchsym_in_class(tobjectdef(srsymtable.defowner),tobjectdef(srsymtable.defowner),s,srsym,srsymtable) then
|
|
|
+ if searchsym_in_class(tobjectdef(srsymtable.defowner),tobjectdef(srsymtable.defowner),s,srsym,srsymtable,true) then
|
|
|
begin
|
|
|
result:=true;
|
|
|
exit;
|
|
@@ -2129,7 +2154,7 @@ implementation
|
|
|
end;
|
|
|
|
|
|
|
|
|
- function searchsym_in_class(classh,contextclassh:tobjectdef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable):boolean;
|
|
|
+ function searchsym_in_class(classh,contextclassh:tobjectdef;const s : TIDString;out srsym:tsym;out srsymtable:TSymtable;searchhelper:boolean):boolean;
|
|
|
var
|
|
|
hashedid : THashedIDString;
|
|
|
orgclass : tobjectdef;
|
|
@@ -2143,8 +2168,11 @@ implementation
|
|
|
classh:=find_real_objcclass_definition(classh,true);
|
|
|
{ The contextclassh is used for visibility. The classh must be equal to
|
|
|
or be a parent of contextclassh. E.g. for inherited searches the classh is the
|
|
|
- parent. }
|
|
|
- if not contextclassh.is_related(classh) then
|
|
|
+ parent or a class helper. }
|
|
|
+ if not (contextclassh.is_related(classh) or
|
|
|
+ (assigned(contextclassh.extendeddef) and
|
|
|
+ (contextclassh.extendeddef.typ=objectdef) and
|
|
|
+ contextclassh.extendeddef.is_related(classh))) then
|
|
|
internalerror(200811161);
|
|
|
end;
|
|
|
result:=false;
|
|
@@ -2164,17 +2192,38 @@ implementation
|
|
|
end;
|
|
|
for i:=0 to classh.ImplementedInterfaces.count-1 do
|
|
|
begin
|
|
|
- if searchsym_in_class(TImplementedInterface(classh.ImplementedInterfaces[i]).intfdef,contextclassh,s,srsym,srsymtable) then
|
|
|
+ if searchsym_in_class(TImplementedInterface(classh.ImplementedInterfaces[i]).intfdef,contextclassh,s,srsym,srsymtable,false) then
|
|
|
begin
|
|
|
result:=true;
|
|
|
exit;
|
|
|
end;
|
|
|
end;
|
|
|
end
|
|
|
+ else
|
|
|
+ if is_objectpascal_helper(classh) then
|
|
|
+ begin
|
|
|
+ { helpers have their own obscure search logic... }
|
|
|
+ result:=searchsym_in_helper(classh,contextclassh,s,srsym,srsymtable,false);
|
|
|
+ if result then
|
|
|
+ exit;
|
|
|
+ end
|
|
|
else
|
|
|
begin
|
|
|
while assigned(classh) do
|
|
|
begin
|
|
|
+ { search for a class helper method first if this is an Object
|
|
|
+ Pascal class }
|
|
|
+ if is_class(classh) and searchhelper then
|
|
|
+ begin
|
|
|
+ result:=search_objectpascal_helper(classh,contextclassh,s,srsym,srsymtable);
|
|
|
+ if result then
|
|
|
+ { if the procsym is overloaded we need to use the
|
|
|
+ "original" symbol; the helper symbol will be found when
|
|
|
+ searching for overloads }
|
|
|
+ if (srsym.typ<>procsym) or
|
|
|
+ not (sp_has_overloaded in tprocsym(srsym).symoptions) then
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
srsymtable:=classh.symtable;
|
|
|
srsym:=tsym(srsymtable.FindWithHash(hashedid));
|
|
|
if assigned(srsym) and
|
|
@@ -2188,7 +2237,7 @@ implementation
|
|
|
end;
|
|
|
end;
|
|
|
if is_objcclass(orgclass) then
|
|
|
- result:=search_class_helper(orgclass,s,srsym,srsymtable)
|
|
|
+ result:=search_objc_helper(orgclass,s,srsym,srsymtable)
|
|
|
else
|
|
|
begin
|
|
|
srsym:=nil;
|
|
@@ -2202,6 +2251,15 @@ implementation
|
|
|
begin
|
|
|
result:=false;
|
|
|
hashedid.id:=s;
|
|
|
+ { search for a record helper method first }
|
|
|
+ result:=search_objectpascal_helper(recordh,recordh,s,srsym,srsymtable);
|
|
|
+ if result then
|
|
|
+ { if the procsym is overloaded we need to use the
|
|
|
+ "original" symbol; the helper symbol will be found when
|
|
|
+ searching for overloads }
|
|
|
+ if (srsym.typ<>procsym) or
|
|
|
+ not (sp_has_overloaded in tprocsym(srsym).symoptions) then
|
|
|
+ exit;
|
|
|
srsymtable:=recordh.symtable;
|
|
|
srsym:=tsym(srsymtable.FindWithHash(hashedid));
|
|
|
if assigned(srsym) and is_visible_for_object(srsym,recordh) then
|
|
@@ -2287,6 +2345,64 @@ implementation
|
|
|
srsymtable:=nil;
|
|
|
end;
|
|
|
|
|
|
+ function searchsym_in_helper(classh,contextclassh:tobjectdef;const s: TIDString;out srsym:tsym;out srsymtable:TSymtable;aHasInherited:boolean):boolean;
|
|
|
+ var
|
|
|
+ hashedid : THashedIDString;
|
|
|
+ parentclassh : tobjectdef;
|
|
|
+ begin
|
|
|
+ result:=false;
|
|
|
+ if not is_objectpascal_helper(classh) then
|
|
|
+ Internalerror(2011030101);
|
|
|
+ hashedid.id:=s;
|
|
|
+ { in a helper things are a bit more complex:
|
|
|
+ 1. search the symbol in the helper (if not "inherited")
|
|
|
+ 2. search the symbol in the extended type
|
|
|
+ 3. search the symbol in the parent helpers
|
|
|
+ 4. only classes: search the symbol in the parents of the extended type
|
|
|
+ }
|
|
|
+ if not aHasInherited then
|
|
|
+ begin
|
|
|
+ { search in the helper itself }
|
|
|
+ srsymtable:=classh.symtable;
|
|
|
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
|
|
|
+ if assigned(srsym) and
|
|
|
+ is_visible_for_object(srsym,contextclassh) then
|
|
|
+ begin
|
|
|
+ addsymref(srsym);
|
|
|
+ result:=true;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ { now search in the extended type itself }
|
|
|
+ srsymtable:=classh.extendeddef.symtable;
|
|
|
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
|
|
|
+ if assigned(srsym) and
|
|
|
+ is_visible_for_object(srsym,contextclassh) then
|
|
|
+ begin
|
|
|
+ addsymref(srsym);
|
|
|
+ result:=true;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ { now search in the parent helpers }
|
|
|
+ parentclassh:=classh.childof;
|
|
|
+ while assigned(parentclassh) do
|
|
|
+ begin
|
|
|
+ srsymtable:=parentclassh.symtable;
|
|
|
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
|
|
|
+ if assigned(srsym) and
|
|
|
+ is_visible_for_object(srsym,contextclassh) then
|
|
|
+ begin
|
|
|
+ addsymref(srsym);
|
|
|
+ result:=true;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ parentclassh:=parentclassh.childof;
|
|
|
+ end;
|
|
|
+ if is_class(classh.extendeddef) then
|
|
|
+ { now search in the parents of the extended class (with helpers!) }
|
|
|
+ result:=searchsym_in_class(tobjectdef(classh.extendeddef).childof,contextclassh,s,srsym,srsymtable,true);
|
|
|
+ { addsymref is already called by searchsym_in_class }
|
|
|
+ end;
|
|
|
|
|
|
function search_specific_assignment_operator(assignment_type:ttoken;from_def,to_def:Tdef):Tprocdef;
|
|
|
var
|
|
@@ -2436,8 +2552,103 @@ implementation
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+ function search_last_objectpascal_helper(pd,contextclassh : tabstractrecorddef;out odef : tobjectdef):boolean;
|
|
|
+ var
|
|
|
+ s: string;
|
|
|
+ list: TFPObjectList;
|
|
|
+ i: integer;
|
|
|
+ st: tsymtable;
|
|
|
+ begin
|
|
|
+ result:=false;
|
|
|
+ { when there are no helpers active currently then we don't need to do
|
|
|
+ anything }
|
|
|
+ if current_module.extendeddefs.count=0 then
|
|
|
+ exit;
|
|
|
+ { no helpers for anonymous types }
|
|
|
+ if not assigned(pd.objrealname) or (pd.objrealname^='') then
|
|
|
+ exit;
|
|
|
+ { if pd is defined inside a procedure we must not use make_mangledname
|
|
|
+ (as a helper may not be defined in a procedure this is no problem...)}
|
|
|
+ st:=pd.owner;
|
|
|
+ while st.symtabletype in [objectsymtable,recordsymtable] do
|
|
|
+ st:=st.defowner.owner;
|
|
|
+ if st.symtabletype=localsymtable then
|
|
|
+ exit;
|
|
|
+ { the mangled name is used as the key for tmodule.extendeddefs }
|
|
|
+ s:=make_mangledname('',pd.symtable,'');
|
|
|
+ list:=TFPObjectList(current_module.extendeddefs.Find(s));
|
|
|
+ if assigned(list) and (list.count>0) then
|
|
|
+ begin
|
|
|
+ i:=list.count-1;
|
|
|
+ repeat
|
|
|
+ odef:=tobjectdef(list[list.count-1]);
|
|
|
+ result:=(odef.owner.symtabletype in [staticsymtable,globalsymtable]) or
|
|
|
+ is_visible_for_object(tobjectdef(list[i]).typesym,contextclassh);
|
|
|
+ dec(i);
|
|
|
+ until result or (i<0);
|
|
|
+ if not result then
|
|
|
+ { just to be sure that noone uses odef }
|
|
|
+ odef:=nil;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ function search_objectpascal_helper(pd,contextclassh : tabstractrecorddef;const s: string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
|
|
|
- function search_class_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
+ var
|
|
|
+ hashedid : THashedIDString;
|
|
|
+ classh : tobjectdef;
|
|
|
+ i : integer;
|
|
|
+ pdef : tprocdef;
|
|
|
+ begin
|
|
|
+ result:=false;
|
|
|
+
|
|
|
+ { if there is no class helper for the class then there is no need to
|
|
|
+ search further }
|
|
|
+ if not search_last_objectpascal_helper(pd,contextclassh,classh) then
|
|
|
+ exit;
|
|
|
+
|
|
|
+ hashedid.id:=s;
|
|
|
+
|
|
|
+ repeat
|
|
|
+ srsymtable:=classh.symtable;
|
|
|
+ srsym:=tsym(srsymtable.FindWithHash(hashedid));
|
|
|
+
|
|
|
+ if srsym<>nil then
|
|
|
+ begin
|
|
|
+ if srsym.typ=propertysym then
|
|
|
+ begin
|
|
|
+ result:=true;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ for i:=0 to tprocsym(srsym).procdeflist.count-1 do
|
|
|
+ begin
|
|
|
+ pdef:=tprocdef(tprocsym(srsym).procdeflist[i]);
|
|
|
+ if not is_visible_for_object(pdef.owner,pdef.visibility,contextclassh) then
|
|
|
+ continue;
|
|
|
+ { we need to know if a procedure references symbols
|
|
|
+ in the static symtable, because then it can't be
|
|
|
+ inlined from outside this unit }
|
|
|
+ if assigned(current_procinfo) and
|
|
|
+ (srsym.owner.symtabletype=staticsymtable) then
|
|
|
+ include(current_procinfo.flags,pi_uses_static_symtable);
|
|
|
+ { the first found method wins }
|
|
|
+ srsym:=tprocdef(tprocsym(srsym).procdeflist[i]).procsym;
|
|
|
+ srsymtable:=srsym.owner;
|
|
|
+ addsymref(srsym);
|
|
|
+ result:=true;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ { try the helper parent if available }
|
|
|
+ classh:=classh.childof;
|
|
|
+ until classh=nil;
|
|
|
+
|
|
|
+ srsym:=nil;
|
|
|
+ srsymtable:=nil;
|
|
|
+ end;
|
|
|
+
|
|
|
+ function search_objc_helper(pd : tobjectdef;const s : string; out srsym: tsym; out srsymtable: tsymtable):boolean;
|
|
|
var
|
|
|
hashedid : THashedIDString;
|
|
|
stackitem : psymtablestackitem;
|
|
@@ -2563,6 +2774,8 @@ implementation
|
|
|
{ in case this is a formal objcclass, first find the real definition }
|
|
|
if (oo_is_formal in pd.objectoptions) then
|
|
|
pd:=find_real_objcclass_definition(tobjectdef(pd),true);
|
|
|
+ if search_objectpascal_helper(pd, pd, s, result, srsymtable) then
|
|
|
+ exit;
|
|
|
hashedid.id:=s;
|
|
|
orgpd:=pd;
|
|
|
while assigned(pd) do
|
|
@@ -2581,7 +2794,7 @@ implementation
|
|
|
|
|
|
{ not found, now look for class helpers }
|
|
|
if is_objcclass(pd) then
|
|
|
- search_class_helper(tobjectdef(orgpd),s,result,srsymtable)
|
|
|
+ search_objc_helper(tobjectdef(orgpd),s,result,srsymtable)
|
|
|
else
|
|
|
result:=nil;
|
|
|
end;
|
|
@@ -2645,8 +2858,24 @@ implementation
|
|
|
{ returns the default property of a class, searches also anchestors }
|
|
|
var
|
|
|
_defaultprop : tpropertysym;
|
|
|
+ helperpd : tobjectdef;
|
|
|
begin
|
|
|
_defaultprop:=nil;
|
|
|
+ { first search in helper's hierarchy }
|
|
|
+ if search_last_objectpascal_helper(pd,nil,helperpd) then
|
|
|
+ while assigned(helperpd) do
|
|
|
+ begin
|
|
|
+ helperpd.symtable.SymList.ForEachCall(@tstoredsymtable(helperpd.symtable).testfordefaultproperty,@_defaultprop);
|
|
|
+ if assigned(_defaultprop) then
|
|
|
+ break;
|
|
|
+ helperpd:=helperpd.childof;
|
|
|
+ end;
|
|
|
+ if assigned(_defaultprop) then
|
|
|
+ begin
|
|
|
+ search_default_property:=_defaultprop;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ { now search in the type's hierarchy itself }
|
|
|
while assigned(pd) do
|
|
|
begin
|
|
|
pd.symtable.SymList.ForEachCall(@tstoredsymtable(pd.symtable).testfordefaultproperty,@_defaultprop);
|