procdefutil.pas 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754
  1. {
  2. Copyright (c) 2018 by Jonas Maebe
  3. Copyright (c) 2011-2021 by Blaise.ru
  4. This unit provides helpers for creating procdefs
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$i fpcdefs.inc}
  19. unit procdefutil;
  20. interface
  21. uses
  22. globtype,procinfo,
  23. symconst,symtype,symdef,
  24. node,nbas;
  25. { create a nested procdef that will be used to outline code from a procedure;
  26. astruct should usually be nil, except in special cases like the Windows SEH
  27. exception handling funclets }
  28. function create_outline_procdef(const basesymname: string; astruct: tabstractrecorddef; potype: tproctypeoption; resultdef: tdef): tprocdef;
  29. procedure convert_to_funcref_intf(const n:tidstring;var def:tdef);
  30. function adjust_funcref(var def:tdef;sym,dummysym:tsym):boolean;
  31. { functionality related to capturing local variables for anonymous functions }
  32. function get_or_create_capturer(pd:tprocdef):tsym;
  33. function capturer_add_anonymous_proc(owner:tprocinfo;pd:tprocdef;out capturer:tsym):tobjectdef;
  34. function capturer_add_procvar_or_proc(owner:tprocinfo;n:tnode;out capturer:tsym;out capturen:tnode):tobjectdef;
  35. procedure initialize_capturer(ctx:tprocinfo;var stmt:tstatementnode);
  36. procedure postprocess_capturer(ctx:tprocinfo);
  37. procedure convert_captured_syms(pd:tprocdef;tree:tnode);
  38. implementation
  39. uses
  40. cutils,cclasses,verbose,globals,
  41. fmodule,
  42. pass_1,
  43. nobj,ncal,nmem,nld,nutils,
  44. ngenutil,
  45. symbase,symsym,symtable,defutil,defcmp,
  46. htypechk,
  47. pparautl,psub;
  48. function create_outline_procdef(const basesymname: string; astruct: tabstractrecorddef; potype: tproctypeoption; resultdef: tdef): tprocdef;
  49. var
  50. st:TSymTable;
  51. checkstack: psymtablestackitem;
  52. oldsymtablestack: tsymtablestack;
  53. sym:tprocsym;
  54. begin
  55. { get actual procedure symtable (skip withsymtables, etc.) }
  56. st:=nil;
  57. checkstack:=symtablestack.stack;
  58. while assigned(checkstack) do
  59. begin
  60. st:=checkstack^.symtable;
  61. if st.symtabletype in [staticsymtable,globalsymtable,localsymtable] then
  62. break;
  63. checkstack:=checkstack^.next;
  64. end;
  65. { Create a nested procedure, even from main_program_level.
  66. Furthermore, force procdef and procsym into the same symtable
  67. (by default, defs are registered with symtablestack.top which may be
  68. something temporary like exceptsymtable - in that case, procdef can be
  69. destroyed before procsym, leaving invalid pointers). }
  70. oldsymtablestack:=symtablestack;
  71. symtablestack:=nil;
  72. result:=cprocdef.create(max(normal_function_level,st.symtablelevel)+1,true);
  73. result.returndef:=resultdef;
  74. { if the parent is a generic or a specialization, the new function is one
  75. as well }
  76. if st.symtabletype=localsymtable then
  77. result.defoptions:=result.defoptions+(tstoreddef(st.defowner).defoptions*[df_generic,df_specialization]);
  78. symtablestack:=oldsymtablestack;
  79. st.insertdef(result);
  80. result.struct:=astruct;
  81. { tabstractprocdef constructor sets po_delphi_nested_cc whenever
  82. nested procvars modeswitch is active. We must be independent of this switch. }
  83. exclude(result.procoptions,po_delphi_nested_cc);
  84. result.proctypeoption:=potype;
  85. { always use the default calling convention }
  86. result.proccalloption:=pocall_default;
  87. include(result.procoptions,po_hascallingconvention);
  88. handle_calling_convention(result,hcc_default_actions_impl);
  89. sym:=cprocsym.create(basesymname+result.unique_id_str);
  90. st.insertsym(sym);
  91. result.procsym:=sym;
  92. proc_add_definition(result);
  93. { the code will be assigned directly to the "code" field later }
  94. result.forwarddef:=false;
  95. result.aliasnames.insert(result.mangledname);
  96. end;
  97. function fileinfo_to_suffix(const fileinfo:tfileposinfo):tsymstr;inline;
  98. begin
  99. result:=tostr(fileinfo.moduleindex)+'_'+
  100. tostr(fileinfo.fileindex)+'_'+
  101. tostr(fileinfo.line)+'_'+
  102. tostr(fileinfo.column);
  103. end;
  104. const
  105. anon_funcref_prefix='$FuncRef_';
  106. capturer_class_name='$CapturerClass';
  107. { the leading $ is only added when registering the var symbol }
  108. capturer_var_name='Capturer';
  109. keepalive_suffix='_keepalive';
  110. outer_self_field_name='OuterSelf';
  111. procedure convert_to_funcref_intf(const n:tidstring;var def:tdef);
  112. var
  113. oldsymtablestack : tsymtablestack;
  114. pvdef : tprocvardef absolute def;
  115. intfdef : tobjectdef;
  116. invokedef : tprocdef;
  117. psym : tprocsym;
  118. sym : tsym;
  119. st : tsymtable;
  120. i : longint;
  121. name : tidstring;
  122. begin
  123. if def.typ<>procvardef then
  124. internalerror(2021040201);
  125. if not (po_is_function_ref in tprocvardef(pvdef).procoptions) then
  126. internalerror(2021022101);
  127. if n='' then
  128. name:=anon_funcref_prefix+fileinfo_to_suffix(current_filepos)
  129. else
  130. name:=n;
  131. intfdef:=cobjectdef.create(odt_interfacecom,name,interface_iunknown,true);
  132. include(intfdef.objectoptions,oo_is_funcref);
  133. include(intfdef.objectoptions,oo_is_invokable);
  134. include(intfdef.objectoptions,oo_has_virtual);
  135. intfdef.typesym:=pvdef.typesym;
  136. pvdef.typesym:=nil;
  137. intfdef.defoptions:=intfdef.defoptions+pvdef.defoptions*[df_generic,df_specialization];
  138. { also inherit the general flags from the surrounding structured type or
  139. function }
  140. if assigned(current_structdef) then
  141. begin
  142. intfdef.defoptions:=intfdef.defoptions+current_structdef.defoptions*[df_generic,df_specialization];
  143. end
  144. else if assigned(current_procinfo) then
  145. begin
  146. intfdef.defoptions:=intfdef.defoptions+current_procinfo.procdef.defoptions*[df_generic,df_specialization];
  147. end;
  148. if cs_generate_rtti in current_settings.localswitches then
  149. include(intfdef.objectoptions,oo_can_have_published);
  150. oldsymtablestack:=symtablestack;
  151. symtablestack:=nil;
  152. invokedef:=tprocdef(pvdef.getcopyas(procdef,pc_normal_no_paras,'',false));
  153. invokedef.struct:=intfdef;
  154. invokedef.forwarddef:=false;
  155. include(invokedef.procoptions,po_overload);
  156. include(invokedef.procoptions,po_virtualmethod);
  157. invokedef.procsym:=cprocsym.create(method_name_funcref_invoke_decl);
  158. if cs_generate_rtti in current_settings.localswitches then
  159. invokedef.visibility:=vis_published
  160. else
  161. invokedef.visibility:=vis_public;
  162. intfdef.symtable.insertsym(invokedef.procsym);
  163. intfdef.symtable.insertdef(invokedef);
  164. { we need to do this even if the def isn't a generic/specialization itself,
  165. but *belongs* to one }
  166. if intfdef.defoptions*[df_generic,df_specialization]<>[] then
  167. begin
  168. if assigned(pvdef.genericdef) and (pvdef.genericdef.typ<>objectdef) then
  169. internalerror(2021040501);
  170. intfdef.genericdef:=pvdef.genericdef;
  171. { in case of a generic we move all involved syms/defs to the interface }
  172. intfdef.genericparas:=pvdef.genericparas;
  173. pvdef.genericparas:=nil;
  174. if assigned(intfdef.genericparas) then
  175. for i:=0 to intfdef.genericparas.count-1 do
  176. begin
  177. sym:=tsym(intfdef.genericparas[i]);
  178. if sym.owner<>pvdef.parast then
  179. continue;
  180. sym.changeowner(intfdef.symtable);
  181. if (sym.typ=typesym) and (ttypesym(sym).typedef.owner=pvdef.parast) then
  182. ttypesym(sym).typedef.changeowner(intfdef.symtable);
  183. end;
  184. end;
  185. { now move the symtable over }
  186. invokedef.parast.free;
  187. invokedef.parast:=pvdef.parast;
  188. invokedef.parast.defowner:=invokedef;
  189. pvdef.parast:=nil;
  190. for i:=0 to invokedef.parast.symlist.count-1 do
  191. begin
  192. sym:=tsym(invokedef.parast.symlist[i]);
  193. if sym.typ<>paravarsym then
  194. continue;
  195. if tparavarsym(sym).vardef=pvdef then
  196. tparavarsym(sym).vardef:=intfdef;
  197. end;
  198. symtablestack:=oldsymtablestack;
  199. if invokedef.returndef=pvdef then
  200. invokedef.returndef:=intfdef;
  201. handle_calling_convention(invokedef,hcc_default_actions_intf_struct);
  202. proc_add_definition(invokedef);
  203. invokedef.calcparas;
  204. { def is not owned, so it can be simply freed }
  205. def.free;
  206. def:=intfdef;
  207. end;
  208. function adjust_funcref(var def:tdef;sym,dummysym:tsym):boolean;
  209. var
  210. sympos : tfileposinfo;
  211. name : string;
  212. begin
  213. result:=false;
  214. if (def.typ<>procvardef) and not is_funcref(def) then
  215. internalerror(2022020401);
  216. if assigned(sym) and not (sym.typ=typesym) then
  217. internalerror(2022020402);
  218. { these always support everything, no "of object" or
  219. "is_nested" is allowed }
  220. if is_nested_pd(tprocvardef(def)) or
  221. is_methodpointer(def) then
  222. cgmessage(type_e_function_reference_kind);
  223. if not (po_is_block in tprocvardef(def).procoptions) then
  224. begin
  225. if assigned(dummysym) then
  226. ttypesym(dummysym).typedef:=nil;
  227. if assigned(sym) then
  228. begin
  229. ttypesym(sym).typedef:=nil;
  230. name:=sym.name;
  231. end
  232. else
  233. name:='';
  234. convert_to_funcref_intf(name,def);
  235. if assigned(sym) then
  236. ttypesym(sym).typedef:=def;
  237. if assigned(dummysym) then
  238. ttypesym(dummysym).typedef:=def;
  239. build_vmt(tobjectdef(def));
  240. result:=true;
  241. end
  242. else
  243. begin
  244. if assigned(sym) and (sym.refs>0) then
  245. begin
  246. { find where the symbol was used and trigger
  247. a "symbol not completely defined" error }
  248. if not fileinfo_of_typesym_in_def(def,sym,sympos) then
  249. sympos:=sym.fileinfo;
  250. messagepos1(sympos,type_e_type_is_not_completly_defined,sym.realname);
  251. end;
  252. end;
  253. end;
  254. function funcref_intf_for_proc(pd:tabstractprocdef;const suffix:string):tobjectdef;
  255. var
  256. name : tsymstr;
  257. sym : tsym;
  258. symowner : tsymtable;
  259. oldsymtablestack: TSymtablestack;
  260. invokedef: tprocdef;
  261. begin
  262. if pd.is_generic then
  263. internalerror(2022010710);
  264. name:='funcrefintf_'+suffix;
  265. if pd.owner.symtabletype=globalsymtable then
  266. symowner:=current_module.localsymtable
  267. else
  268. symowner:=pd.owner;
  269. sym:=tsym(symowner.find(name));
  270. if assigned(sym) then
  271. begin
  272. if sym.typ<>typesym then
  273. internalerror(2022010708);
  274. if not is_funcref(ttypesym(sym).typedef) then
  275. internalerror(2022010709);
  276. result:=tobjectdef(ttypesym(sym).typedef);
  277. exit;
  278. end;
  279. name:='$'+name;
  280. result:=cobjectdef.create(odt_interfacecom,name,interface_iunknown,false);
  281. include(result.objectoptions,oo_is_funcref);
  282. include(result.objectoptions,oo_is_invokable);
  283. sym:=ctypesym.create(name,result);
  284. oldsymtablestack:=symtablestack;
  285. symtablestack:=nil;
  286. invokedef:=tprocdef(pd.getcopyas(procdef,pc_normal_no_hidden,'',false));
  287. invokedef.struct:=result;
  288. invokedef.visibility:=vis_public;
  289. invokedef.procsym:=cprocsym.create(method_name_funcref_invoke_decl);
  290. invokedef.parast.symtablelevel:=normal_function_level;
  291. invokedef.localst.symtablelevel:=normal_function_level;
  292. include(invokedef.procoptions,po_virtualmethod);
  293. exclude(invokedef.procoptions,po_staticmethod);
  294. exclude(invokedef.procoptions,po_classmethod);
  295. invokedef.forwarddef:=false;
  296. symtablestack:=oldsymtablestack;
  297. result.symtable.insertsym(invokedef.procsym);
  298. result.symtable.insertdef(invokedef);
  299. proc_add_definition(invokedef);
  300. invokedef.calcparas;
  301. include(result.objectoptions,oo_has_virtual);
  302. symowner.insertsym(sym);
  303. symowner.insertdef(result);
  304. addsymref(sym);
  305. build_vmt(result);
  306. end;
  307. {.$define DEBUG_CAPTURER}
  308. function acceptable_typ(sym:tabstractvarsym;typ :tsymtyp) : boolean;
  309. begin
  310. acceptable_typ:=false;
  311. if (sym.typ=typ) then
  312. acceptable_typ:=true
  313. else if (sym.typ=absolutevarsym) and (tabsolutevarsym(sym).reftyp=typ) then
  314. acceptable_typ:=true;
  315. end;
  316. function get_capturer(pd:tprocdef):tabstractvarsym;
  317. function getsym(st:tsymtable;typ:tsymtyp):tabstractvarsym;
  318. begin
  319. result:=tabstractvarsym(st.find(capturer_var_name));
  320. if not assigned(result) then
  321. internalerror(2022010703);
  322. if not acceptable_typ(result,typ) then
  323. internalerror(2022010704);
  324. if not is_class(result.vardef) then
  325. internalerror(2022010705);
  326. end;
  327. begin
  328. case pd.proctypeoption of
  329. potype_unitfinalize,
  330. potype_unitinit,
  331. potype_proginit:
  332. begin
  333. if not assigned(pd.owner) then
  334. internalerror(2022052401);
  335. if pd.owner.symtabletype<>staticsymtable then
  336. internalerror(2022052402);
  337. result:=getsym(pd.owner,staticvarsym);
  338. end;
  339. else
  340. begin
  341. if not assigned(pd.localst) then
  342. internalerror(2022020502);
  343. result:=getsym(pd.localst,localvarsym);
  344. end;
  345. end;
  346. end;
  347. function get_capturer_alive(pd:tprocdef):tabstractvarsym;
  348. function getsym(st:tsymtable;typ:tsymtyp):tabstractvarsym;
  349. begin
  350. result:=tabstractvarsym(st.find(capturer_var_name+keepalive_suffix));
  351. if not assigned(result) then
  352. internalerror(2022051703);
  353. if not acceptable_typ(result,typ) then
  354. internalerror(2022051704);
  355. if not is_interfacecom(result.vardef) then
  356. internalerror(2022051705);
  357. end;
  358. begin
  359. case pd.proctypeoption of
  360. potype_unitfinalize,
  361. potype_unitinit,
  362. potype_proginit:
  363. begin
  364. if not assigned(pd.owner) then
  365. internalerror(2022052403);
  366. if pd.owner.symtabletype<>staticsymtable then
  367. internalerror(2022052404);
  368. result:=getsym(pd.owner,staticvarsym);
  369. end;
  370. else
  371. begin
  372. if not assigned(pd.localst) then
  373. internalerror(2022051702);
  374. result:=getsym(pd.localst,localvarsym);
  375. end;
  376. end;
  377. end;
  378. function get_or_create_capturer(pd:tprocdef):tsym;
  379. var
  380. name : tsymstr;
  381. parent,
  382. def : tobjectdef;
  383. typesym : tsym;
  384. keepalive : tabstractvarsym;
  385. intfimpl : TImplementedInterface;
  386. st : tsymtable;
  387. begin
  388. if pd.has_capturer then
  389. begin
  390. result:=get_capturer(pd);
  391. end
  392. else
  393. begin
  394. parent:=tobjectdef(search_system_type('TINTERFACEDOBJECT').typedef);
  395. if not is_class(parent) then
  396. internalerror(2022010706);
  397. name:=capturer_class_name+'_'+fileinfo_to_suffix(pd.fileinfo);
  398. case pd.proctypeoption of
  399. potype_unitfinalize,
  400. potype_unitinit,
  401. potype_proginit:
  402. st:=pd.owner;
  403. else
  404. st:=pd.localst;
  405. end;
  406. def:=cobjectdef.create(odt_class,name,parent,false);
  407. include(def.objectoptions,oo_is_capturer);
  408. typesym:=ctypesym.create(name,def);
  409. typesym.fileinfo:=pd.fileinfo;
  410. st.insertdef(def);
  411. st.insertsym(typesym);
  412. addsymref(typesym);
  413. if df_generic in pd.defoptions then
  414. include(def.defoptions,df_generic);
  415. { don't set df_specialization as in that case genericdef needs to be
  416. set, but the local symtables are freed once a unit is finished }
  417. {if df_specialization in pd.defoptions then
  418. begin
  419. if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
  420. internalerror(2022020501);
  421. def.genericdef:=tstoreddef(get_capturer(tprocdef(pd.genericdef)).vardef);
  422. include(def.defoptions,df_specialization);
  423. end;}
  424. if st.symtabletype=localsymtable then
  425. result:=clocalvarsym.create('$'+capturer_var_name,vs_value,def,[vo_is_internal])
  426. else
  427. result:=cstaticvarsym.create('$'+capturer_var_name,vs_value,def,[vo_is_internal]);
  428. result.fileinfo:=pd.fileinfo;
  429. st.insertsym(result);
  430. addsymref(result);
  431. if st.symtabletype=localsymtable then
  432. keepalive:=clocalvarsym.create('$'+capturer_var_name+keepalive_suffix,vs_value,interface_iunknown,[vo_is_internal])
  433. else
  434. keepalive:=cstaticvarsym.create('$'+capturer_var_name+keepalive_suffix,vs_value,interface_iunknown,[vo_is_internal]);
  435. keepalive.fileinfo:=pd.fileinfo;
  436. st.insertsym(keepalive);
  437. addsymref(keepalive);
  438. if st.symtabletype<>localsymtable then
  439. begin
  440. cnodeutils.insertbssdata(tstaticvarsym(result));
  441. cnodeutils.insertbssdata(tstaticvarsym(keepalive));
  442. end;
  443. { avoid warnings as these symbols are initialized using initialize_capturer
  444. after parsing the body }
  445. tabstractvarsym(result).varstate:=vs_readwritten;
  446. keepalive.varstate:=vs_readwritten;
  447. pd.has_capturer:=true;
  448. end;
  449. end;
  450. function can_be_captured(sym:tsym;curpd:tprocdef):boolean;
  451. begin
  452. result:=false;
  453. if (sym.typ=procsym) and assigned(curpd) and (curpd.procsym=sym) then
  454. exit(true);
  455. if not (sym.typ in [localvarsym,paravarsym]) then
  456. exit;
  457. if tabstractnormalvarsym(sym).varoptions*[vo_is_result,vo_is_funcret]<>[] then
  458. exit;
  459. if sym.typ=paravarsym then
  460. begin
  461. if (tparavarsym(sym).varspez in [vs_out,vs_var]) and
  462. not (vo_is_self in tparavarsym(sym).varoptions) then
  463. exit;
  464. if is_open_array(tparavarsym(sym).vardef) then
  465. exit;
  466. end;
  467. result:=true;
  468. end;
  469. type
  470. tsym_mapping = record
  471. oldsym:tsym;
  472. newsym:tsym;
  473. end;
  474. psym_mapping = ^tsym_mapping;
  475. function replace_self_sym(var n:tnode;arg:pointer):foreachnoderesult;
  476. var
  477. mapping : psym_mapping absolute arg;
  478. ld : tloadnode;
  479. begin
  480. if n.nodetype=loadn then
  481. begin
  482. ld:=tloadnode(n);
  483. if ld.symtableentry=mapping^.oldsym then
  484. begin
  485. ld.symtableentry:=mapping^.newsym;
  486. { make sure that the node is processed again }
  487. ld.resultdef:=nil;
  488. if assigned(ld.left) then
  489. begin
  490. { no longer loaded through the frame pointer }
  491. ld.left.free;
  492. ld.left:=nil;
  493. end;
  494. typecheckpass(n);
  495. end;
  496. end;
  497. result:=fen_true;
  498. end;
  499. procedure capture_captured_syms(pd:tprocdef;owner:tprocinfo;capturedef:tobjectdef;oldpd:tprocdef);
  500. var
  501. curpd : tprocdef;
  502. subcapturer : tobjectdef;
  503. symstodo : TFPList;
  504. i : longint;
  505. sym : tsym;
  506. fieldsym : tfieldvarsym;
  507. fieldname : tsymstr;
  508. fielddef : tdef;
  509. begin
  510. if not pd.was_anonymous or not assigned(pd.capturedsyms) or (pd.capturedsyms.count=0) then
  511. exit;
  512. { capture all variables that the original procdef captured }
  513. curpd:=owner.procdef;
  514. subcapturer:=capturedef;
  515. symstodo:=tfplist.create;
  516. for i:=0 to pd.capturedsyms.count-1 do
  517. if can_be_captured(pcapturedsyminfo(pd.capturedsyms[i])^.sym,oldpd) and
  518. (pcapturedsyminfo(pd.capturedsyms[i])^.sym.typ<>procsym) then
  519. symstodo.add(pcapturedsyminfo(pd.capturedsyms[i])^.sym);
  520. while symstodo.count>0 do
  521. begin
  522. { we know we have symbols left to capture thus we either have a
  523. symbol that's located in the capturer of the current procdef or
  524. we need to put in the OuterSelf reference }
  525. if curpd=owner.procdef then
  526. subcapturer:=capturedef
  527. else
  528. subcapturer:=tobjectdef(tabstractvarsym(get_or_create_capturer(curpd)).vardef);
  529. i:=0;
  530. while i<symstodo.count do
  531. begin
  532. sym:=tsym(symstodo[i]);
  533. if (sym.owner=curpd.localst) or
  534. (sym.owner=curpd.parast) then
  535. begin
  536. {$ifdef DEBUG_CAPTURER}writeln('Symbol ',sym.name,' captured from ',curpd.procsym.name);{$endif}
  537. { the symbol belongs to the current procdef, so add a field to
  538. the capturer if it doesn't already exist }
  539. if vo_is_self in tabstractnormalvarsym(sym).varoptions then
  540. fieldname:=outer_self_field_name
  541. else
  542. fieldname:=sym.name;
  543. fieldsym:=tfieldvarsym(subcapturer.symtable.find(fieldname));
  544. if not assigned(fieldsym) then
  545. begin
  546. {$ifdef DEBUG_CAPTURER}writeln('Adding field ',fieldname,' to ',subcapturer.typesym.name);{$endif}
  547. fielddef:=tabstractvarsym(sym).vardef;
  548. if vo_is_self in tabstractnormalvarsym(sym).varoptions then
  549. begin
  550. fieldname:='$'+fieldname;
  551. if not is_implicit_pointer_object_type(fielddef) then
  552. fielddef:=cpointerdef.getreusable(fielddef);
  553. end;
  554. fieldsym:=cfieldvarsym.create(fieldname,vs_value,fielddef,[]);
  555. fieldsym.fileinfo:=sym.fileinfo;
  556. subcapturer.symtable.insertsym(fieldsym);
  557. tabstractrecordsymtable(subcapturer.symtable).addfield(fieldsym,vis_public);
  558. end;
  559. if not assigned(tabstractnormalvarsym(sym).capture_sym) then
  560. tabstractnormalvarsym(sym).capture_sym:=fieldsym
  561. else if tabstractnormalvarsym(sym).capture_sym<>fieldsym then
  562. internalerror(2022011602);
  563. symstodo.delete(i);
  564. end
  565. else if sym=pd.procsym then
  566. { no explicit capturing needed here }
  567. symstodo.delete(i)
  568. else
  569. inc(i);
  570. end;
  571. if symstodo.count>0 then
  572. begin
  573. if curpd.owner.symtabletype<>localsymtable then
  574. internalerror(2022011001);
  575. { there are still symbols left, so before we move to the parent
  576. procdef we add the OuterSelf field to set up the chain of
  577. capturers }
  578. {$ifdef DEBUG_CAPTURER}writeln('Initialize capturer for ',curpd.procsym.name);{$endif}
  579. { we no longer need the curpd, but we need the parent, so change
  580. curpd here }
  581. curpd:=tprocdef(curpd.owner.defowner);
  582. if curpd.typ<>procdef then
  583. internalerror(2022011002);
  584. if not assigned(subcapturer.symtable.find(outer_self_field_name)) then
  585. begin
  586. {$ifdef DEBUG_CAPTURER}writeln('Adding field OuterSelf to ',subcapturer.typesym.name);{$endif}
  587. if subcapturer.owner.symtablelevel>normal_function_level then
  588. begin
  589. { the outer self is the capturer of the outer procdef }
  590. sym:=get_or_create_capturer(curpd);
  591. { ensure that the outer capturer isn't put into a register anymore }
  592. tabstractvarsym(sym).different_scope:=true;
  593. tabstractvarsym(sym).varregable:=vr_none;
  594. end
  595. else
  596. begin
  597. { the outer self is the self of the method }
  598. if not (curpd.owner.symtabletype in [objectsymtable,recordsymtable]) then
  599. internalerror(2022011603);
  600. sym:=tsym(curpd.parast.find('self'));
  601. if not assigned(sym) then
  602. internalerror(2022011604);
  603. end;
  604. { add the keep alive IUnknown symbol }
  605. fieldsym:=cfieldvarsym.create('$'+outer_self_field_name+keepalive_suffix,vs_value,interface_iunknown,[]);
  606. fieldsym.fileinfo:=sym.fileinfo;
  607. subcapturer.symtable.insertsym(fieldsym);
  608. tabstractrecordsymtable(subcapturer.symtable).addfield(fieldsym,vis_public);
  609. { add the capturer symbol }
  610. fieldsym:=cfieldvarsym.create('$'+outer_self_field_name,vs_value,tabstractvarsym(sym).vardef,[]);
  611. fieldsym.fileinfo:=sym.fileinfo;
  612. subcapturer.symtable.insertsym(fieldsym);
  613. tabstractrecordsymtable(subcapturer.symtable).addfield(fieldsym,vis_public);
  614. if (sym.typ=paravarsym) and (vo_is_self in tparavarsym(sym).varoptions) then
  615. begin
  616. if assigned(tparavarsym(sym).capture_sym) then
  617. internalerror(2022011705);
  618. tparavarsym(sym).capture_sym:=fieldsym;
  619. end;
  620. end;
  621. end;
  622. end;
  623. symstodo.free;
  624. symstodo := nil;
  625. end;
  626. function retrieve_sym_for_filepos(var n:tnode;arg:pointer):foreachnoderesult;
  627. var
  628. sym : ^tsym absolute arg;
  629. begin
  630. if assigned(sym^) then
  631. exit(fen_norecurse_true);
  632. result:=fen_false;
  633. if not (n.resultdef.typ in [procdef,procvardef]) then
  634. exit;
  635. if n.nodetype=loadn then
  636. begin
  637. sym^:=tloadnode(n).symtableentry;
  638. result:=fen_norecurse_true;
  639. end
  640. else if n.nodetype=subscriptn then
  641. begin
  642. sym^:=tsubscriptnode(n).vs;
  643. result:=fen_norecurse_true;
  644. end;
  645. end;
  646. function collect_syms_to_capture(var n:tnode;arg:pointer):foreachnoderesult;
  647. var
  648. pd : tprocdef absolute arg;
  649. sym : tsym;
  650. begin
  651. result:=fen_false;
  652. if n.nodetype<>loadn then
  653. exit;
  654. sym:=tsym(tloadnode(n).symtableentry);
  655. if not (sym.owner.symtabletype in [parasymtable,localsymtable]) then
  656. exit;
  657. if sym.owner.symtablelevel>normal_function_level then begin
  658. pd.add_captured_sym(sym,tloadnode(n).resultdef,n.fileinfo);
  659. result:=fen_true;
  660. end;
  661. end;
  662. type
  663. tselfinfo=record
  664. selfsym:tsym;
  665. ignore:tsym;
  666. end;
  667. pselfinfo=^tselfinfo;
  668. function find_self_sym(var n:tnode;arg:pointer):foreachnoderesult;
  669. var
  670. info : pselfinfo absolute arg;
  671. begin
  672. result:=fen_false;
  673. if assigned(info^.selfsym) then
  674. exit(fen_norecurse_true);
  675. if n.nodetype<>loadn then
  676. exit;
  677. if tloadnode(n).symtableentry.typ<>paravarsym then
  678. exit;
  679. if tloadnode(n).symtableentry=info^.ignore then
  680. exit;
  681. if vo_is_self in tparavarsym(tloadnode(n).symtableentry).varoptions then
  682. begin
  683. info^.selfsym:=tparavarsym(tloadnode(n).symtableentry);
  684. result:=fen_norecurse_true;
  685. end;
  686. end;
  687. function find_outermost_loaded_sym(var n:tnode;arg:pointer):foreachnoderesult;
  688. var
  689. sym : ^tsym absolute arg;
  690. begin
  691. if assigned(sym^) then
  692. exit(fen_norecurse_true);
  693. result:=fen_false;
  694. if n.nodetype<>loadn then
  695. exit;
  696. if not (n.resultdef.typ in [procdef,procvardef]) then
  697. exit;
  698. sym^:=tloadnode(n).symtableentry;
  699. result:=fen_norecurse_true;
  700. end;
  701. function find_procdef(var n:tnode;arg:pointer):foreachnoderesult;
  702. var
  703. pd : ^tprocdef absolute arg;
  704. begin
  705. if assigned(pd^) then
  706. exit(fen_norecurse_true);
  707. result:=fen_false;
  708. if n.resultdef.typ<>procdef then
  709. exit;
  710. pd^:=tprocdef(n.resultdef);
  711. result:=fen_norecurse_true;
  712. end;
  713. function capturer_add_procvar_or_proc(owner:tprocinfo;n:tnode;out capturer:tsym;out capturen:tnode):tobjectdef;
  714. function create_paras(pd:tprocdef):tcallparanode;
  715. var
  716. para : tparavarsym;
  717. i : longint;
  718. begin
  719. result:=nil;
  720. for i:=0 to pd.paras.count-1 do
  721. begin
  722. para:=tparavarsym(pd.paras[i]);
  723. if vo_is_hidden_para in para.varoptions then
  724. continue;
  725. result:=ccallparanode.create(cloadnode.create(para,pd.parast),result);
  726. end;
  727. end;
  728. function find_nested_procinfo(pd:tprocdef):tcgprocinfo;
  729. var
  730. tmp,
  731. res : tprocinfo;
  732. begin
  733. tmp:=owner;
  734. while assigned(tmp) and (tmp.procdef.parast.symtablelevel>=normal_function_level) do
  735. begin
  736. res:=tmp.find_nestedproc_by_pd(pd);
  737. if assigned(res) then
  738. exit(tcgprocinfo(res));
  739. tmp:=tmp.parent;
  740. end;
  741. result:=nil;
  742. end;
  743. procedure swap_symtable(var st1,st2:tsymtable);
  744. var
  745. st : tsymtable;
  746. owner : tdefentry;
  747. level : byte;
  748. begin
  749. { first swap the symtables themselves }
  750. st:=st1;
  751. st1:=st2;
  752. st2:=st;
  753. { then swap the symtables' owners }
  754. owner:=st1.defowner;
  755. st1.defowner:=st2.defowner;
  756. st2.defowner:=owner;
  757. { and finally the symtable level }
  758. level:=st1.symtablelevel;
  759. st1.symtablelevel:=st2.symtablelevel;
  760. st2.symtablelevel:=level;
  761. end;
  762. procedure print_procinfo(pi:tcgprocinfo);
  763. begin
  764. { Print the node to tree.log }
  765. if paraprintnodetree <> 0 then
  766. pi.printproc('after parsing');
  767. {$ifdef DEBUG_NODE_XML}
  768. { Methods of generic classes don't get any code generated, so output
  769. the node tree here }
  770. if (df_generic in pi.procdef.defoptions) then
  771. pi.XMLPrintProc(True);
  772. {$endif DEBUG_NODE_XML}
  773. end;
  774. var
  775. ps : tprocsym;
  776. oldpd,
  777. pd : tprocdef;
  778. pinested,
  779. pi : tcgprocinfo;
  780. sym,
  781. fpsym,
  782. selfsym : tsym;
  783. invokename : tsymstr;
  784. capturedef : tobjectdef;
  785. capturesyms : tfplist;
  786. captured : pcapturedsyminfo;
  787. implintf : TImplementedInterface;
  788. i : longint;
  789. stmt : tstatementnode;
  790. n1 : tnode;
  791. fieldsym : tfieldvarsym;
  792. selfinfo : tselfinfo;
  793. begin
  794. if not (n.resultdef.typ in [procdef,procvardef]) then
  795. internalerror(2022022101);
  796. capturer:=nil;
  797. capturen:=nil;
  798. pinested:=nil;
  799. oldpd:=nil;
  800. { determine a unique name for the variable, field for function of the
  801. node we're trying to load }
  802. sym:=nil;
  803. if not foreachnodestatic(pm_preprocess,n,@find_outermost_loaded_sym,@sym) then
  804. internalerror(2022022102);
  805. result:=funcref_intf_for_proc(tabstractprocdef(n.resultdef),fileinfo_to_suffix(sym.fileinfo));
  806. if (sym.typ=procsym) and (sym.owner.symtabletype=localsymtable) then
  807. begin
  808. { this is assigning a nested function, so retrieve the correct procdef
  809. so that we can then retrieve the procinfo for it }
  810. if n.resultdef.typ=procdef then
  811. pd:=tprocdef(n.resultdef)
  812. else
  813. begin
  814. pd:=nil;
  815. if not foreachnodestatic(pm_preprocess,n,@find_procdef,@pd) then
  816. internalerror(2022041801);
  817. if not assigned(pd) then
  818. internalerror(2022041802);
  819. end;
  820. { check whether all captured symbols can indeed be captured }
  821. capturesyms:=pd.capturedsyms;
  822. if assigned(capturesyms) then
  823. for i:=0 to capturesyms.count-1 do
  824. begin
  825. captured:=pcapturedsyminfo(capturesyms[i]);
  826. if not can_be_captured(captured^.sym,pd) then
  827. MessagePos1(captured^.fileinfo,sym_e_symbol_no_capture,captured^.sym.realname);
  828. end;
  829. if not (df_generic in owner.procdef.defoptions) then
  830. begin
  831. pinested:=find_nested_procinfo(pd);
  832. if not assigned(pinested) then
  833. internalerror(2022041803);
  834. oldpd:=pd;
  835. if pinested.parent<>owner then
  836. begin
  837. { we need to capture this into the owner of the nested function
  838. instead }
  839. owner:=pinested;
  840. capturer:=get_or_create_capturer(pinested.procdef);
  841. if not assigned(capturer) then
  842. internalerror(2022041804);
  843. end;
  844. end;
  845. end
  846. else if (n.resultdef.typ=procvardef) and
  847. (po_delphi_nested_cc in tprocvardef(n.resultdef).procoptions) then
  848. begin
  849. MessagePos(n.fileinfo,type_e_nested_procvar_to_funcref);
  850. exit;
  851. end
  852. else
  853. pinested:=nil;
  854. if df_generic in owner.procdef.defoptions then
  855. exit;
  856. if not assigned(capturer) then
  857. capturer:=get_or_create_capturer(owner.procdef);
  858. if not (capturer.typ in [localvarsym,staticvarsym]) then
  859. internalerror(2022022103);
  860. capturedef:=tobjectdef(tabstractvarsym(capturer).vardef);
  861. if not is_class(capturedef) then
  862. internalerror(2022022104);
  863. implintf:=find_implemented_interface(capturedef,result);
  864. if assigned(implintf) then
  865. begin
  866. { this is already captured into a method of the capturer, so nothing
  867. further to do }
  868. exit;
  869. end;
  870. implintf:=capturedef.register_implemented_interface(result,true);
  871. invokename:=method_name_funcref_invoke_decl+'__FPCINTERNAL__'+fileinfo_to_suffix(sym.fileinfo);
  872. ps:=cprocsym.create(invokename);
  873. pd:=tprocdef(tabstractprocdef(n.resultdef).getcopyas(procdef,pc_normal_no_hidden,'',false));
  874. pd.aliasnames.clear;
  875. pd.procsym:=ps;
  876. pd.struct:=capturedef;
  877. pd.changeowner(capturedef.symtable);
  878. pd.parast.symtablelevel:=normal_function_level;
  879. pd.localst.symtablelevel:=normal_function_level;
  880. { reset procoptions }
  881. pd.procoptions:=[];
  882. ps.ProcdefList.Add(pd);
  883. pd.forwarddef:=false;
  884. { set procinfo and current_procinfo.procdef }
  885. pi:=tcgprocinfo(cprocinfo.create(nil));
  886. pi.procdef:=pd;
  887. if not assigned(pinested) then
  888. begin
  889. insert_funcret_para(pd);
  890. insert_funcret_local(pd);
  891. { we always do a call, namely to the provided function }
  892. include(pi.flags,pi_do_call);
  893. end
  894. else
  895. begin
  896. { the original nested function now calls the method }
  897. include(pinested.flags,pi_do_call);
  898. { swap the para and local symtables of the nested and new routine }
  899. swap_symtable(pinested.procdef.parast,pd.parast);
  900. swap_symtable(pinested.procdef.localst,pd.localst);
  901. { fix function return symbol }
  902. pd.funcretsym:=pinested.procdef.funcretsym;
  903. pinested.procdef.funcretsym:=nil;
  904. pinested.procdef.reset_after_conv;
  905. insert_funcret_para(pinested.procdef);
  906. insert_funcret_local(pinested.procdef);
  907. { the nested function needs access to the parent's framepointer to
  908. access the capturer }
  909. insert_parentfp_para(pinested.procdef);
  910. pd.copied_from:=pinested.procdef;
  911. end;
  912. { to simplify some checks, but only after insert_funcret_para }
  913. pd.was_anonymous:=true;
  914. capturedef.symtable.insertsym(ps);
  915. owner.addnestedproc(pi);
  916. { remove self and parentfp parameter if any as that will be replaced by
  917. the capturer }
  918. selfsym:=nil;
  919. fpsym:=nil;
  920. for i:=0 to pd.parast.symlist.count-1 do
  921. begin
  922. sym:=tsym(pd.parast.symlist[i]);
  923. if sym.typ<>paravarsym then
  924. continue;
  925. if vo_is_self in tparavarsym(sym).varoptions then
  926. selfsym:=sym
  927. else if vo_is_parentfp in tparavarsym(sym).varoptions then
  928. fpsym:=sym;
  929. if assigned(selfsym) and assigned(fpsym) then
  930. break;
  931. end;
  932. if assigned(selfsym) then
  933. pd.parast.deletesym(selfsym);
  934. if assigned(fpsym) then
  935. pd.parast.deletesym(fpsym);
  936. pd.calcparas;
  937. if assigned(pinested) then
  938. pinested.procdef.calcparas;
  939. insert_self_and_vmt_para(pd);
  940. if assigned(pinested) then
  941. begin
  942. { when we're assigning a nested function to a function reference we
  943. move the code of the nested function to the newly created capturer
  944. method (including the captured symbols) and have the original nested
  945. function simply call that function-turned-method }
  946. pi.code:=pinested.code;
  947. pinested.code:=internalstatements(stmt);
  948. end
  949. else
  950. pi.code:=internalstatements(stmt);
  951. selfinfo.selfsym:=nil;
  952. selfinfo.ignore:=nil;
  953. fieldsym:=nil;
  954. if assigned(pinested) then
  955. begin
  956. n1:=ccallnode.create(create_paras(pinested.procdef),ps,capturedef.symtable,cloadnode.create(capturer,capturer.owner),[],nil);
  957. { captured variables cannot be in registers }
  958. make_not_regable(tcallnode(n1).methodpointer,[ra_addr_regable,ra_addr_taken]);
  959. end
  960. else if n.resultdef.typ=procvardef then
  961. begin
  962. { store the procvar in a field so that it won't be changed if the
  963. procvar itself is changed }
  964. fieldsym:=cfieldvarsym.create('$'+fileinfo_to_suffix(n.fileinfo),vs_value,n.resultdef,[]);
  965. fieldsym.fileinfo:=n.fileinfo;
  966. capturedef.symtable.insertsym(fieldsym);
  967. tabstractrecordsymtable(capturedef.symtable).addfield(fieldsym,vis_public);
  968. capturen:=csubscriptnode.create(fieldsym,cloadnode.create(capturer,capturer.owner));
  969. selfsym:=tsym(pd.parast.find('self'));
  970. if not assigned(selfsym) then
  971. internalerror(2022052301);
  972. selfinfo.ignore:=selfsym;
  973. n1:=ccallnode.create_procvar(create_paras(pd),csubscriptnode.create(fieldsym,cloadnode.create(selfsym,selfsym.owner)));
  974. end
  975. else
  976. begin
  977. if n.nodetype<>loadn then
  978. internalerror(2022032401);
  979. if tloadnode(n).symtableentry.typ<>procsym then
  980. internalerror(2022032402);
  981. n1:=ccallnode.create(create_paras(pd),tprocsym(tloadnode(n).symtableentry),tloadnode(n).symtable,tloadnode(n).left,[],nil);
  982. tloadnode(n).left:=nil;
  983. end;
  984. if assigned(pd.returndef) and not is_void(pd.returndef) then
  985. begin
  986. if assigned(pinested) then
  987. sym:=pinested.procdef.funcretsym
  988. else
  989. sym:=pd.funcretsym;
  990. n1:=cassignmentnode.create(
  991. cloadnode.create(sym,sym.owner),
  992. n1
  993. );
  994. { captured variables cannot be in registers }
  995. make_not_regable(tassignmentnode(n1).left,[ra_addr_regable,ra_addr_taken]);
  996. end;
  997. addstatement(stmt,n1);
  998. pd.aliasnames.insert(pd.mangledname);
  999. if assigned(pinested) then
  1000. begin
  1001. { transfer all captured syms }
  1002. capturesyms:=pinested.procdef.capturedsyms;
  1003. if assigned(capturesyms) then
  1004. begin
  1005. for i:=0 to capturesyms.count-1 do
  1006. begin
  1007. captured:=pcapturedsyminfo(capturesyms[i]);
  1008. pi.add_captured_sym(captured^.sym,captured^.def,captured^.fileinfo);
  1009. dispose(captured);
  1010. end;
  1011. capturesyms.clear;
  1012. end;
  1013. { the original nested function now needs to capture only the capturer }
  1014. pinested.procdef.add_captured_sym(capturer,capturedef,n.fileinfo);
  1015. end
  1016. { does this need to capture Self? }
  1017. else if not foreachnodestatic(pm_postprocess,n,@find_self_sym,@selfinfo) then
  1018. begin
  1019. { is this a method of the current class? }
  1020. if (n.resultdef.typ=procdef) and
  1021. assigned(tprocdef(n.resultdef).struct) and
  1022. not (po_staticmethod in tprocdef(n.resultdef).procoptions) and
  1023. assigned(current_procinfo.procdef.struct) and
  1024. def_is_related(current_procinfo.procdef.struct,tprocdef(n.resultdef).struct) then
  1025. begin
  1026. selfinfo.selfsym:=tsym(current_procinfo.procdef.parast.find('self'));
  1027. if not assigned(selfinfo.selfsym) then
  1028. internalerror(2022110601);
  1029. end
  1030. else
  1031. { does this need some other local variable or parameter? }
  1032. foreachnodestatic(pm_postprocess,n,@collect_syms_to_capture,@pd)
  1033. end;
  1034. if assigned(selfinfo.selfsym) and not assigned(fieldsym) then
  1035. { this isn't a procdef that was captured into a field, so capture the
  1036. self }
  1037. pd.add_captured_sym(selfinfo.selfsym,tabstractvarsym(selfinfo.selfsym).vardef,n.fileinfo);
  1038. print_procinfo(pi);
  1039. if assigned(pinested) then
  1040. print_procinfo(pinested);
  1041. implintf.AddMapping(upcase(result.objrealname^+'.')+method_name_funcref_invoke_find,upcase(invokename));
  1042. capture_captured_syms(pd,owner,capturedef,oldpd);
  1043. end;
  1044. function capturer_add_anonymous_proc(owner:tprocinfo;pd:tprocdef;out capturer:tsym):tobjectdef;
  1045. var
  1046. capturedef : tobjectdef;
  1047. implintf : TImplementedInterface;
  1048. invokename : tsymstr;
  1049. i : longint;
  1050. outerself,
  1051. fpsym,
  1052. selfsym,
  1053. sym : tsym;
  1054. info : pcapturedsyminfo;
  1055. pi : tprocinfo;
  1056. mapping : tsym_mapping;
  1057. invokedef,
  1058. parentdef,
  1059. curpd : tprocdef;
  1060. begin
  1061. capturer:=nil;
  1062. result:=funcref_intf_for_proc(pd,fileinfo_to_suffix(pd.fileinfo));
  1063. if df_generic in pd.defoptions then
  1064. begin
  1065. if (po_anonymous in pd.procoptions) and
  1066. assigned(pd.capturedsyms) and
  1067. (pd.capturedsyms.count>0) then
  1068. begin
  1069. { only check whether the symbols can be captured, but don't
  1070. convert anything to avoid problems }
  1071. for i:=0 to pd.capturedsyms.count-1 do
  1072. begin
  1073. info:=pcapturedsyminfo(pd.capturedsyms[i]);
  1074. if not can_be_captured(info^.sym,pd) then
  1075. MessagePos1(info^.fileinfo,sym_e_symbol_no_capture,info^.sym.realname)
  1076. end;
  1077. end;
  1078. exit;
  1079. end;
  1080. capturer:=get_or_create_capturer(owner.procdef);
  1081. if not (capturer.typ in [localvarsym,staticvarsym]) then
  1082. internalerror(2022010711);
  1083. capturedef:=tobjectdef(tabstractvarsym(capturer).vardef);
  1084. if not is_class(capturedef) then
  1085. internalerror(2022010712);
  1086. implintf:=find_implemented_interface(capturedef,result);
  1087. if assigned(implintf) then
  1088. begin
  1089. { this can only already be an implemented interface if a named procdef
  1090. was assigned to a function ref at an earlier point, an anonymous
  1091. function can be used only once }
  1092. if po_anonymous in pd.procoptions then
  1093. internalerror(2022010713);
  1094. exit;
  1095. end;
  1096. implintf:=capturedef.register_implemented_interface(result,true);
  1097. invokename:=method_name_funcref_invoke_decl+'__FPCINTERNAL__'+fileinfo_to_suffix(pd.fileinfo);
  1098. if po_anonymous in pd.procoptions then
  1099. begin
  1100. { turn the anonymous function into a method of the capturer }
  1101. pd.changeowner(capturedef.symtable);
  1102. pd.struct:=capturedef;
  1103. exclude(pd.procoptions,po_anonymous);
  1104. exclude(pd.procoptions,po_delphi_nested_cc);
  1105. exclude(pd.procoptions,po_staticmethod);
  1106. exclude(pd.procoptions,po_classmethod);
  1107. pd.was_anonymous:=true;
  1108. pd.procsym.ChangeOwnerAndName(capturedef.symtable,upcase(invokename));
  1109. pd.procsym.realname:=invokename;
  1110. pd.parast.symtablelevel:=normal_function_level;
  1111. pd.localst.symtablelevel:=normal_function_level;
  1112. { retrieve framepointer and self parameters if any }
  1113. fpsym:=nil;
  1114. selfsym:=nil;
  1115. for i:=0 to pd.parast.symlist.count-1 do
  1116. begin
  1117. sym:=tsym(pd.parast.symlist[i]);
  1118. if sym.typ<>paravarsym then
  1119. continue;
  1120. if vo_is_parentfp in tparavarsym(sym).varoptions then
  1121. fpsym:=sym
  1122. else if vo_is_self in tparavarsym(sym).varoptions then
  1123. selfsym:=sym;
  1124. if assigned(fpsym) and assigned(selfsym) then
  1125. break;
  1126. end;
  1127. { get rid of the framepointer parameter }
  1128. if assigned(fpsym) then
  1129. pd.parast.deletesym(fpsym);
  1130. outerself:=nil;
  1131. { complain about all symbols that can't be captured and add the symbols
  1132. to this procdefs capturedsyms if it isn't a top level function }
  1133. if assigned(pd.capturedsyms) and (pd.capturedsyms.count>0) then
  1134. begin
  1135. for i:=0 to pd.capturedsyms.count-1 do
  1136. begin
  1137. info:=pcapturedsyminfo(pd.capturedsyms[i]);
  1138. if not can_be_captured(info^.sym,pd) then
  1139. MessagePos1(info^.fileinfo,sym_e_symbol_no_capture,info^.sym.realname)
  1140. else if info^.sym=selfsym then
  1141. begin
  1142. { we need to replace the captured "dummy" self parameter
  1143. with the real self parameter symbol from the surrounding
  1144. method }
  1145. if not assigned(outerself) then
  1146. outerself:=tsym(owner.get_normal_proc.procdef.parast.find('self'));
  1147. if not assigned(outerself) then
  1148. internalerror(2022010905);
  1149. { the anonymous function can only be a direct child of the
  1150. owner }
  1151. pi:=owner.get_first_nestedproc;
  1152. while assigned(pi) do
  1153. begin
  1154. if pi.procdef=pd then
  1155. break;
  1156. pi:=tprocinfo(pi.next);
  1157. end;
  1158. if not assigned(pi) then
  1159. internalerror(2022010906);
  1160. mapping.oldsym:=selfsym;
  1161. mapping.newsym:=outerself;
  1162. { replace all uses of the captured Self by the new Self
  1163. parameter }
  1164. foreachnodestatic(pm_preprocess,tcgprocinfo(pi).code,@replace_self_sym,@mapping);
  1165. { update the captured symbol }
  1166. info^.sym:=outerself;
  1167. info^.def:=tabstractvarsym(outerself).vardef;
  1168. end
  1169. else if info^.sym.owner.defowner<>owner.procdef then
  1170. owner.procdef.add_captured_sym(info^.sym,info^.def,info^.fileinfo);
  1171. end;
  1172. end;
  1173. { delete the original self parameter }
  1174. if assigned(selfsym) then
  1175. pd.parast.deletesym(selfsym);
  1176. { note: don't call insert_self_and_vmt_para here, as that is later on
  1177. done when building the VMT }
  1178. end
  1179. else
  1180. internalerror(2022022201);
  1181. implintf.AddMapping(upcase(result.objrealname^+'.')+method_name_funcref_invoke_find,upcase(invokename));
  1182. capture_captured_syms(pd,owner,capturedef,nil);
  1183. end;
  1184. function load_capturer(capturer:tabstractvarsym):tnode;inline;
  1185. begin
  1186. result:=cloadnode.create(capturer,capturer.owner);
  1187. end;
  1188. function instantiate_capturer(capturer_sym:tabstractvarsym):tnode;
  1189. var
  1190. capturer_def : tobjectdef;
  1191. ctor : tprocsym;
  1192. begin
  1193. capturer_def:=tobjectdef(capturer_sym.vardef);
  1194. { Neither TInterfacedObject, nor TCapturer have a custom constructor }
  1195. ctor:=tprocsym(class_tobject.symtable.Find('CREATE'));
  1196. if not assigned(ctor) then
  1197. internalerror(2022010801);
  1198. { Insert "Capturer := TCapturer.Create()" as the first statement of the routine }
  1199. result:=cloadvmtaddrnode.create(ctypenode.create(capturer_def));
  1200. result:=ccallnode.create(nil,ctor,capturer_def.symtable,result,[],nil);
  1201. result:=cassignmentnode.create(load_capturer(capturer_sym),result);
  1202. end;
  1203. procedure initialize_captured_paras(pd:tprocdef;capturer:tabstractvarsym;var stmt:tstatementnode);
  1204. var
  1205. i : longint;
  1206. psym: tparavarsym;
  1207. n : tnode;
  1208. begin
  1209. for i:=0 to pd.paras.count-1 do
  1210. begin
  1211. psym:=tparavarsym(pd.paras[i]);
  1212. if not psym.is_captured then
  1213. continue;
  1214. {$ifdef DEBUG_CAPTURER}writeln(#9'initialize captured parameter ',psym.RealName);{$endif}
  1215. n:=cloadnode.create(psym,psym.owner);
  1216. if psym.capture_sym.owner.defowner<>capturer.vardef then
  1217. internalerror(2022010903);
  1218. if (vo_is_self in psym.varoptions) and not is_implicit_pointer_object_type(psym.vardef) then
  1219. n:=caddrnode.create(n);
  1220. n:=cassignmentnode.create(
  1221. csubscriptnode.create(psym.capture_sym,cloadnode.create(capturer,capturer.owner)),
  1222. n
  1223. );
  1224. addstatement(stmt,n);
  1225. end;
  1226. end;
  1227. procedure attach_outer_capturer(ctx:tprocinfo;capturer:tabstractvarsym;var stmt:tstatementnode);
  1228. var
  1229. alivefield,
  1230. selffield : tfieldvarsym;
  1231. outeralive,
  1232. outercapturer : tabstractvarsym;
  1233. alivenode,
  1234. selfnode : tnode;
  1235. begin
  1236. if not ctx.procdef.was_anonymous and
  1237. not (ctx.procdef.owner.symtabletype=localsymtable) then
  1238. exit;
  1239. selffield:=tfieldvarsym(tobjectdef(capturer.vardef).symtable.find(outer_self_field_name));
  1240. if not assigned(selffield) then
  1241. { we'll simply assume that we don't need the outer capturer }
  1242. exit;
  1243. alivefield:=tfieldvarsym(tobjectdef(capturer.vardef).symtable.find(outer_self_field_name+keepalive_suffix));
  1244. if not assigned(alivefield) then
  1245. internalerror(2022051701);
  1246. if ctx.procdef.was_anonymous then
  1247. begin
  1248. selfnode:=load_self_node;
  1249. alivenode:=selfnode.getcopy;
  1250. end
  1251. else
  1252. begin
  1253. outercapturer:=get_capturer(tprocdef(ctx.procdef.owner.defowner));
  1254. if not assigned(outercapturer) then
  1255. internalerror(2022011605);
  1256. selfnode:=cloadnode.create(outercapturer,outercapturer.owner);
  1257. make_not_regable(selfnode,[ra_different_scope]);
  1258. outeralive:=get_capturer_alive(tprocdef(ctx.procdef.owner.defowner));
  1259. if not assigned(outeralive) then
  1260. internalerror(2022051706);
  1261. alivenode:=cloadnode.create(outeralive,outeralive.owner);
  1262. make_not_regable(alivenode,[ra_different_scope]);
  1263. end;
  1264. addstatement(stmt,cassignmentnode.create(
  1265. csubscriptnode.create(
  1266. selffield,
  1267. cloadnode.create(
  1268. capturer,
  1269. capturer.owner
  1270. )
  1271. ),
  1272. selfnode));
  1273. addstatement(stmt,cassignmentnode.create(
  1274. csubscriptnode.create(
  1275. alivefield,
  1276. cloadnode.create(
  1277. capturer,
  1278. capturer.owner
  1279. )
  1280. ),
  1281. alivenode));
  1282. end;
  1283. procedure initialize_capturer(ctx:tprocinfo;var stmt:tstatementnode);
  1284. var
  1285. capturer_sym,
  1286. keepalive_sym : tabstractvarsym;
  1287. begin
  1288. if ctx.procdef.has_capturer then
  1289. begin
  1290. capturer_sym:=get_capturer(ctx.procdef);
  1291. {$ifdef DEBUG_CAPTURER}writeln('initialize_capturer @ ',ctx.procdef.procsym.RealName);{$endif}
  1292. addstatement(stmt,instantiate_capturer(capturer_sym));
  1293. attach_outer_capturer(ctx,capturer_sym,stmt);
  1294. initialize_captured_paras(ctx.procdef,capturer_sym,stmt);
  1295. keepalive_sym:=get_capturer_alive(ctx.procdef);
  1296. if not assigned(keepalive_sym) then
  1297. internalerror(2022010701);
  1298. addstatement(stmt,cassignmentnode.create(cloadnode.create(keepalive_sym,keepalive_sym.owner),load_capturer(capturer_sym)));
  1299. end;
  1300. end;
  1301. procedure postprocess_capturer(ctx: tprocinfo);
  1302. var
  1303. def: tobjectdef;
  1304. begin
  1305. if not ctx.procdef.has_capturer then
  1306. exit;
  1307. def:=tobjectdef(get_capturer(ctx.procdef).vardef);
  1308. {$ifdef DEBUG_CAPTURER}writeln('process capturer ',def.typesym.Name);{$endif}
  1309. { These two are delayed until this point because
  1310. ... we have been adding fields on-the-fly }
  1311. tabstractrecordsymtable(def.symtable).addalignmentpadding;
  1312. { ... we have been adding interfaces on-the-fly }
  1313. build_vmt(def);
  1314. end;
  1315. type
  1316. tconvert_arg=record
  1317. mappings:tfplist;
  1318. end;
  1319. pconvert_arg=^tconvert_arg;
  1320. tconvert_mapping=record
  1321. oldsym:tsym;
  1322. newsym:tsym;
  1323. olddef:tdef;
  1324. selfnode:tnode;
  1325. end;
  1326. pconvert_mapping=^tconvert_mapping;
  1327. function convert_captured_sym(var n:tnode;arg:pointer):foreachnoderesult;
  1328. var
  1329. convertarg : pconvert_arg absolute arg;
  1330. mapping : pconvert_mapping;
  1331. i : longint;
  1332. old_filepos : tfileposinfo;
  1333. loadprocvar : boolean;
  1334. paras,
  1335. mp : tnode;
  1336. cnf : tcallnodeflags;
  1337. paraold,
  1338. paranew : tcallparanode;
  1339. begin
  1340. result:=fen_true;
  1341. if not (n.nodetype in [loadn,calln]) then
  1342. exit;
  1343. for i:=0 to convertarg^.mappings.count-1 do
  1344. begin
  1345. mapping:=convertarg^.mappings[i];
  1346. case n.nodetype of
  1347. loadn:
  1348. begin
  1349. if tloadnode(n).symtableentry<>mapping^.oldsym then
  1350. continue;
  1351. old_filepos:=current_filepos;
  1352. current_filepos:=n.fileinfo;
  1353. loadprocvar:=nf_load_procvar in n.flags;
  1354. n.free;
  1355. n:=csubscriptnode.create(mapping^.newsym,mapping^.selfnode.getcopy);
  1356. if loadprocvar then
  1357. include(n.flags,nf_load_procvar);
  1358. if (mapping^.oldsym.typ=paravarsym) and
  1359. (vo_is_self in tparavarsym(mapping^.oldsym).varoptions) and
  1360. not is_implicit_pointer_object_type(tparavarsym(mapping^.oldsym).vardef) then
  1361. n:=cderefnode.create(n);
  1362. typecheckpass(n);
  1363. current_filepos:=old_filepos;
  1364. break;
  1365. end;
  1366. calln:
  1367. begin
  1368. if mapping^.oldsym.typ<>procsym then
  1369. continue;
  1370. if tcallnode(n).symtableprocentry<>tprocsym(mapping^.oldsym) then
  1371. continue;
  1372. if tcallnode(n).procdefinition<>tprocdef(mapping^.olddef) then
  1373. continue;
  1374. old_filepos:=current_filepos;
  1375. current_filepos:=n.fileinfo;
  1376. loadprocvar:=nf_load_procvar in n.flags;
  1377. paras:=tcallnode(n).left;
  1378. paraold:=tcallparanode(paras);
  1379. paranew:=nil;
  1380. while assigned(paraold) do
  1381. begin
  1382. if not (vo_is_hidden_para in paraold.parasym.varoptions) then
  1383. begin
  1384. paranew:=ccallparanode.create(paraold.left,paranew);
  1385. paraold.left:=nil;
  1386. end;
  1387. paraold:=tcallparanode(paraold.right);
  1388. end;
  1389. reverseparameters(paranew);
  1390. if assigned(tcallnode(n).methodpointer) then
  1391. internalerror(2023120802);
  1392. cnf:=tcallnode(n).callnodeflags;
  1393. n.free;
  1394. n:=ccallnode.create(paranew,tprocsym(mapping^.newsym),mapping^.newsym.owner,mapping^.selfnode.getcopy,cnf,nil);
  1395. if loadprocvar then
  1396. include(n.flags,nf_load_procvar);
  1397. typecheckpass(n);
  1398. current_filepos:=old_filepos;
  1399. break;
  1400. end;
  1401. else
  1402. internalerror(2023120801);
  1403. end;
  1404. end;
  1405. end;
  1406. procedure convert_captured_syms(pd:tprocdef;tree:tnode);
  1407. function self_tree_for_sym(selfsym:tsym;fieldsym:tsym):tnode;
  1408. var
  1409. fieldowner : tdef;
  1410. newsym : tsym;
  1411. begin
  1412. result:=cloadnode.create(selfsym,selfsym.owner);
  1413. fieldowner:=tdef(fieldsym.owner.defowner);
  1414. newsym:=selfsym;
  1415. while (tabstractvarsym(newsym).vardef<>fieldowner) do
  1416. begin
  1417. newsym:=tsym(tobjectdef(tabstractvarsym(newsym).vardef).symtable.find(outer_self_field_name));
  1418. if not assigned(newsym) then
  1419. internalerror(2022011101);
  1420. result:=csubscriptnode.create(newsym,result);
  1421. end;
  1422. end;
  1423. var
  1424. i,j : longint;
  1425. capturer : tobjectdef;
  1426. tocapture,
  1427. capturedsyms : tfplist;
  1428. convertarg : tconvert_arg;
  1429. mapping : pconvert_mapping;
  1430. invokepd : tprocdef;
  1431. selfsym,
  1432. sym : tsym;
  1433. info: pcapturedsyminfo;
  1434. begin
  1435. {$ifdef DEBUG_CAPTURER}writeln('Converting captured symbols of ',pd.procsym.name);{$endif}
  1436. convertarg.mappings:=tfplist.create;
  1437. capturedsyms:=tfplist.create;
  1438. if pd.was_anonymous and
  1439. assigned(pd.capturedsyms) and
  1440. (pd.capturedsyms.count>0) then
  1441. begin
  1442. {$ifdef DEBUG_CAPTURER}writeln('Converting symbols of converted anonymous function ',pd.procsym.name);{$endif}
  1443. { this is a converted anonymous function, so rework all symbols that
  1444. now belong to the new Self }
  1445. selfsym:=tsym(pd.parast.find('self'));
  1446. if not assigned(selfsym) then
  1447. internalerror(2022010809);
  1448. for i:=0 to pd.capturedsyms.count-1 do
  1449. begin
  1450. sym:=tsym(pcapturedsyminfo(pd.capturedsyms[i])^.sym);
  1451. if not can_be_captured(sym,pd) and
  1452. not (
  1453. (sym.typ=procsym) and
  1454. assigned(pd.copied_from) and
  1455. (pd.copied_from.procsym=sym)
  1456. ) then
  1457. continue;
  1458. {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',sym.Name);{$endif}
  1459. new(mapping);
  1460. mapping^.oldsym:=sym;
  1461. if sym.typ=procsym then
  1462. begin
  1463. if not assigned(pd.copied_from) or
  1464. (pd.copied_from.procsym<>sym) then
  1465. internalerror(2023123001);
  1466. mapping^.newsym:=pd.procsym;
  1467. end
  1468. else
  1469. mapping^.newsym:=tabstractnormalvarsym(sym).capture_sym;
  1470. mapping^.olddef:=pcapturedsyminfo(pd.capturedsyms[i])^.def;
  1471. if not assigned(mapping^.newsym) then
  1472. internalerror(2022010810);
  1473. mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
  1474. convertarg.mappings.add(mapping);
  1475. capturedsyms.add(sym);
  1476. end;
  1477. end;
  1478. if (pd.parast.symtablelevel>normal_function_level) and
  1479. assigned(pd.capturedsyms) and
  1480. (pd.capturedsyms.count>0) then
  1481. begin
  1482. if pd.was_anonymous then
  1483. internalerror(2022081201);
  1484. {$ifdef DEBUG_CAPTURER}writeln('Converting symbols of nested function ',pd.procsym.name);{$endif}
  1485. { this is a nested function, so rework all symbols that are used from
  1486. a parent function, but that might have been captured }
  1487. for i:=0 to pd.capturedsyms.count-1 do
  1488. begin
  1489. sym:=tsym(pcapturedsyminfo(pd.capturedsyms[i])^.sym);
  1490. if not can_be_captured(sym,pd) or
  1491. (sym.typ=procsym) or
  1492. not assigned(tabstractnormalvarsym(sym).capture_sym) then
  1493. continue;
  1494. {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',sym.Name);{$endif}
  1495. new(mapping);
  1496. mapping^.oldsym:=sym;
  1497. mapping^.newsym:=tabstractnormalvarsym(sym).capture_sym;
  1498. mapping^.olddef:=pcapturedsyminfo(pd.capturedsyms[i])^.def;
  1499. capturer:=tobjectdef(mapping^.newsym.owner.defowner);
  1500. if not is_class(capturer) then
  1501. internalerror(2022012701);
  1502. if not (capturer.typesym.owner.symtabletype in [localsymtable,staticsymtable]) then
  1503. internalerror(2022012702);
  1504. selfsym:=tsym(capturer.typesym.owner.find(capturer_var_name));
  1505. if not assigned(selfsym) then
  1506. internalerror(2022012703);
  1507. mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
  1508. convertarg.mappings.add(mapping);
  1509. capturedsyms.add(sym);
  1510. end;
  1511. end;
  1512. if pd.has_capturer then
  1513. begin
  1514. {$ifdef DEBUG_CAPTURER}writeln('Converting symbols of function ',pd.procsym.name,' with capturer');{$endif}
  1515. { this procedure has a capturer, so rework all symbols that are
  1516. captured in that capturer }
  1517. selfsym:=get_capturer(pd);
  1518. { only capture those symbols that weren't captured already by one of
  1519. the above if-clauses and thus are now listed in capturedsyms }
  1520. tocapture:=tfplist.create;
  1521. for i:=0 to pd.localst.symlist.count-1 do
  1522. begin
  1523. sym:=tsym(pd.localst.symlist[i]);
  1524. if sym.typ<>localvarsym then
  1525. continue;
  1526. if assigned(tabstractnormalvarsym(sym).capture_sym) then
  1527. if capturedsyms.indexof(sym)<0 then
  1528. tocapture.add(sym);
  1529. end;
  1530. for i:=0 to pd.parast.symlist.count-1 do
  1531. begin
  1532. sym:=tsym(pd.parast.symlist[i]);
  1533. if sym.typ<>paravarsym then
  1534. continue;
  1535. if assigned(tabstractnormalvarsym(sym).capture_sym) and
  1536. { no need to adjust accesses to the outermost Self inside the
  1537. outermost method }
  1538. not (vo_is_self in tabstractvarsym(sym).varoptions) then
  1539. if capturedsyms.indexof(sym)<0 then
  1540. tocapture.add(sym);
  1541. end;
  1542. convertarg.mappings.capacity:=convertarg.mappings.count+tocapture.count;
  1543. for i:=0 to tocapture.count-1 do
  1544. begin
  1545. new(mapping);
  1546. mapping^.oldsym:=tsym(tocapture[i]);
  1547. {$ifdef DEBUG_CAPTURER}writeln('Replacing symbol ',mapping^.oldsym.Name);{$endif}
  1548. mapping^.newsym:=tabstractnormalvarsym(mapping^.oldsym).capture_sym;
  1549. if not assigned(mapping^.newsym) then
  1550. internalerror(2022010805);
  1551. mapping^.selfnode:=self_tree_for_sym(selfsym,mapping^.newsym);
  1552. convertarg.mappings.add(mapping);
  1553. end;
  1554. tocapture.free;
  1555. tocapture := nil;
  1556. end;
  1557. { not required anymore }
  1558. capturedsyms.free;
  1559. capturedsyms := nil;
  1560. if convertarg.mappings.count>0 then
  1561. foreachnodestatic(pm_postprocess,tree,@convert_captured_sym,@convertarg);
  1562. for i:=0 to convertarg.mappings.count-1 do
  1563. begin
  1564. mapping:=pconvert_mapping(convertarg.mappings[i]);
  1565. mapping^.selfnode.free; // no nil needed
  1566. dispose(mapping);
  1567. end;
  1568. convertarg.mappings.free; // no nil needed
  1569. end;
  1570. end.