mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-18 13:59:47 +02:00
+ check if initialization/finalization code uses implicitly thread vars
git-svn-id: trunk@40269 -
This commit is contained in:
parent
e949276d9d
commit
c37c485eb7
@ -1203,6 +1203,46 @@ implementation
|
||||
procdef.has_inlininginfo:=true;
|
||||
end;
|
||||
|
||||
procedure searchthreadvar(p: TObject; arg: pointer);
|
||||
var
|
||||
i : longint;
|
||||
pd : tprocdef;
|
||||
begin
|
||||
case tsym(p).typ of
|
||||
staticvarsym :
|
||||
begin
|
||||
{ local (procedure or unit) variables only need finalization
|
||||
if they are used
|
||||
}
|
||||
if (vo_is_thread_var in tstaticvarsym(p).varoptions) and
|
||||
((tstaticvarsym(p).refs>0) or
|
||||
{ global (unit) variables always need finalization, since
|
||||
they may also be used in another unit
|
||||
}
|
||||
(tstaticvarsym(p).owner.symtabletype=globalsymtable)) and
|
||||
(
|
||||
(tstaticvarsym(p).varspez<>vs_const) or
|
||||
(vo_force_finalize in tstaticvarsym(p).varoptions)
|
||||
) and
|
||||
not(vo_is_funcret in tstaticvarsym(p).varoptions) and
|
||||
not(vo_is_external in tstaticvarsym(p).varoptions) and
|
||||
is_managed_type(tstaticvarsym(p).vardef) then
|
||||
include(current_procinfo.flags,pi_uses_threadvar);
|
||||
end;
|
||||
procsym :
|
||||
begin
|
||||
for i:=0 to tprocsym(p).ProcdefList.Count-1 do
|
||||
begin
|
||||
pd:=tprocdef(tprocsym(p).ProcdefList[i]);
|
||||
if assigned(pd.localst) and
|
||||
(pd.procsym=tprocsym(p)) and
|
||||
(pd.localst.symtabletype<>staticsymtable) then
|
||||
pd.localst.SymList.ForEachCall(@searchthreadvar,arg);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function searchusercode(var n: tnode; arg: pointer): foreachnoderesult;
|
||||
begin
|
||||
@ -1229,6 +1269,19 @@ implementation
|
||||
|
||||
|
||||
procedure tcgprocinfo.generate_code;
|
||||
|
||||
procedure check_for_threadvars_in_initfinal;
|
||||
begin
|
||||
if current_procinfo.procdef.proctypeoption=potype_unitfinalize then
|
||||
begin
|
||||
{ this is also used for initialization of variables in a
|
||||
program which does not have a globalsymtable }
|
||||
if assigned(current_module.globalsymtable) then
|
||||
TSymtable(current_module.globalsymtable).SymList.ForEachCall(@searchthreadvar,nil);
|
||||
TSymtable(current_module.localsymtable).SymList.ForEachCall(@searchthreadvar,nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
old_current_procinfo : tprocinfo;
|
||||
oldmaxfpuregisters : longint;
|
||||
@ -1426,6 +1479,10 @@ implementation
|
||||
(code.nodetype=blockn) and (tblocknode(code).statements=nil) then
|
||||
procdef.isempty:=true;
|
||||
|
||||
{ unit static/global symtables might contain threadvars which are not explicitly used but which might
|
||||
require a tls register, so check for such variables }
|
||||
check_for_threadvars_in_initfinal;
|
||||
|
||||
{ add implicit entry and exit code }
|
||||
add_entry_exit_code;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user