symcreat.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. {
  2. Copyright (c) 2011 by Jonas Maebe
  3. This unit provides helpers for creating new syms/defs based on string
  4. representations.
  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 symcreat;
  20. interface
  21. uses
  22. finput,tokens,scanner,globtype,
  23. symconst,symbase,symtype,symdef;
  24. type
  25. tscannerstate = record
  26. old_scanner: tscannerfile;
  27. old_token: ttoken;
  28. old_c: char;
  29. old_modeswitches: tmodeswitches;
  30. valid: boolean;
  31. end;
  32. { save/restore the scanner state before/after injecting }
  33. procedure replace_scanner(const tempname: string; out sstate: tscannerstate);
  34. procedure restore_scanner(const sstate: tscannerstate);
  35. { parses a (class or regular) method/constructor/destructor declaration from
  36. str, as if it were declared in astruct's declaration body
  37. WARNING: save the scanner state before calling this routine, and restore
  38. when done. }
  39. function str_parse_method_dec(str: ansistring; potype: tproctypeoption; is_classdef: boolean; astruct: tabstractrecorddef; out pd: tprocdef): boolean;
  40. { parses a (class or regular) method/constructor/destructor implementation
  41. from str, as if it appeared in the current unit's implementation section
  42. WARNINGS:
  43. * save the scanner state before calling this routine, and restore when done.
  44. * the code *must* be written in objfpc style
  45. }
  46. function str_parse_method_impl(str: ansistring; usefwpd: tprocdef; is_classdef: boolean):boolean;
  47. { in the JVM, constructors are not automatically inherited (so you can hide
  48. them). To emulate the Pascal behaviour, we have to automatically add
  49. all parent constructors to the current class as well.}
  50. procedure add_missing_parent_constructors_intf(obj: tobjectdef; forcevis: tvisibility);
  51. { goes through all defs in st to add implementations for synthetic methods
  52. added earlier }
  53. procedure add_synthetic_method_implementations(st: tsymtable);
  54. procedure finish_copied_procdef(var pd: tprocdef; const realname: string; newparentst: tsymtable; newstruct: tabstractrecorddef);
  55. { create "parent frame pointer" record skeleton for procdef, in which local
  56. variables and parameters from pd accessed from nested routines can be
  57. stored }
  58. procedure build_parentfpstruct(pd: tprocdef);
  59. { checks whether sym (a local or para of pd) already has a counterpart in
  60. pd's parentfpstruct, and if not adds a new field to the struct with type
  61. "vardef" (can be different from sym's type in case it's a call-by-reference
  62. parameter, which is indicated by addrparam). If it already has a field in
  63. the parentfpstruct, this field is returned. }
  64. function maybe_add_sym_to_parentfpstruct(pd: tprocdef; sym: tsym; vardef: tdef; addrparam: boolean): tsym;
  65. { given a localvarsym or paravarsym of pd, returns the field of the
  66. parentfpstruct corresponding to this sym }
  67. function find_sym_in_parentfpstruct(pd: tprocdef; sym: tsym): tsym;
  68. { replaces all local and paravarsyms that have been mirrored in the
  69. parentfpstruct with aliasvarsyms that redirect to these fields (used to
  70. make sure that references to these syms in the owning procdef itself also
  71. use the ones in the parentfpstructs) }
  72. procedure redirect_parentfpstruct_local_syms(pd: tprocdef);
  73. { finalises the parentfpstruct (alignment padding, ...) }
  74. procedure finish_parentfpstruct(pd: tprocdef);
  75. implementation
  76. uses
  77. cutils,globals,verbose,systems,comphook,fmodule,
  78. symsym,symtable,defutil,
  79. pbase,pdecobj,pdecsub,psub,
  80. node,nbas,nld,nmem,
  81. defcmp,
  82. paramgr
  83. {$ifdef jvm}
  84. ,pjvm
  85. {$endif};
  86. procedure replace_scanner(const tempname: string; out sstate: tscannerstate);
  87. var
  88. old_block_type: tblock_type;
  89. begin
  90. { would require saving of idtoken, pattern etc }
  91. if (token=_ID) then
  92. internalerror(2011032201);
  93. sstate.old_scanner:=current_scanner;
  94. sstate.old_token:=token;
  95. sstate.old_c:=c;
  96. sstate.old_modeswitches:=current_settings.modeswitches;
  97. sstate.valid:=true;
  98. { creating a new scanner resets the block type, while we want to continue
  99. in the current one }
  100. old_block_type:=block_type;
  101. current_scanner:=tscannerfile.Create('_Macro_.'+tempname);
  102. block_type:=old_block_type;
  103. { required for e.g. FpcDeepCopy record method (uses "out" parameter; field
  104. names are escaped via &, so should not cause conflicts }
  105. current_settings.modeswitches:=objfpcmodeswitches;
  106. end;
  107. procedure restore_scanner(const sstate: tscannerstate);
  108. begin
  109. if sstate.valid then
  110. begin
  111. current_scanner.free;
  112. current_scanner:=sstate.old_scanner;
  113. token:=sstate.old_token;
  114. current_settings.modeswitches:=sstate.old_modeswitches;
  115. c:=sstate.old_c;
  116. end;
  117. end;
  118. function str_parse_method_dec(str: ansistring; potype: tproctypeoption; is_classdef: boolean; astruct: tabstractrecorddef; out pd: tprocdef): boolean;
  119. var
  120. oldparse_only: boolean;
  121. begin
  122. Message1(parser_d_internal_parser_string,str);
  123. oldparse_only:=parse_only;
  124. parse_only:=true;
  125. result:=false;
  126. { inject the string in the scanner }
  127. str:=str+'end;';
  128. current_scanner.substitutemacro('meth_head_macro',@str[1],length(str),current_scanner.line_no,current_scanner.inputfile.ref_index);
  129. current_scanner.readtoken(false);
  130. { and parse it... }
  131. case potype of
  132. potype_class_constructor:
  133. pd:=class_constructor_head(astruct);
  134. potype_class_destructor:
  135. pd:=class_destructor_head(astruct);
  136. potype_constructor:
  137. pd:=constructor_head;
  138. potype_destructor:
  139. pd:=destructor_head;
  140. else
  141. pd:=method_dec(astruct,is_classdef);
  142. end;
  143. if assigned(pd) then
  144. result:=true;
  145. parse_only:=oldparse_only;
  146. end;
  147. function str_parse_method_impl(str: ansistring; usefwpd: tprocdef; is_classdef: boolean):boolean;
  148. var
  149. oldparse_only: boolean;
  150. tmpstr: ansistring;
  151. begin
  152. if ((status.verbosity and v_debug)<>0) then
  153. begin
  154. if assigned(usefwpd) then
  155. Message1(parser_d_internal_parser_string,usefwpd.customprocname([pno_proctypeoption,pno_paranames,pno_noclassmarker,pno_noleadingdollar])+str)
  156. else
  157. begin
  158. if is_classdef then
  159. tmpstr:='class '
  160. else
  161. tmpstr:='';
  162. Message1(parser_d_internal_parser_string,tmpstr+str);
  163. end;
  164. end;
  165. oldparse_only:=parse_only;
  166. parse_only:=false;
  167. result:=false;
  168. { inject the string in the scanner }
  169. str:=str+'end;';
  170. current_scanner.substitutemacro('meth_impl_macro',@str[1],length(str),current_scanner.line_no,current_scanner.inputfile.ref_index);
  171. current_scanner.readtoken(false);
  172. { and parse it... }
  173. read_proc(is_classdef,usefwpd);
  174. parse_only:=oldparse_only;
  175. result:=true;
  176. end;
  177. procedure add_missing_parent_constructors_intf(obj: tobjectdef; forcevis: tvisibility);
  178. var
  179. parent: tobjectdef;
  180. def: tdef;
  181. parentpd,
  182. childpd: tprocdef;
  183. i: longint;
  184. srsym: tsym;
  185. srsymtable: tsymtable;
  186. begin
  187. if (oo_is_external in obj.objectoptions) or
  188. not assigned(obj.childof) then
  189. exit;
  190. parent:=obj.childof;
  191. { find all constructor in the parent }
  192. for i:=0 to tobjectsymtable(parent.symtable).deflist.count-1 do
  193. begin
  194. def:=tdef(tobjectsymtable(parent.symtable).deflist[i]);
  195. if (def.typ<>procdef) or
  196. (tprocdef(def).proctypeoption<>potype_constructor) or
  197. not is_visible_for_object(tprocdef(def),obj) then
  198. continue;
  199. parentpd:=tprocdef(def);
  200. { do we have this constructor too? (don't use
  201. search_struct_member/searchsym_in_class, since those will
  202. search parents too) }
  203. if searchsym_in_record(obj,parentpd.procsym.name,srsym,srsymtable) then
  204. begin
  205. { there's a symbol with the same name, is it a constructor
  206. with the same parameters? }
  207. if srsym.typ=procsym then
  208. begin
  209. childpd:=tprocsym(srsym).find_procdef_bytype_and_para(
  210. potype_constructor,parentpd.paras,nil,
  211. [cpo_ignorehidden,cpo_ignoreuniv,cpo_openequalisexact]);
  212. if assigned(childpd) then
  213. continue;
  214. end;
  215. end;
  216. { if we get here, we did not find it in the current objectdef ->
  217. add }
  218. childpd:=tprocdef(parentpd.getcopy);
  219. if forcevis<>vis_none then
  220. childpd.visibility:=forcevis;
  221. finish_copied_procdef(childpd,parentpd.procsym.realname,obj.symtable,obj);
  222. exclude(childpd.procoptions,po_external);
  223. include(childpd.procoptions,po_overload);
  224. childpd.synthetickind:=tsk_anon_inherited;
  225. include(obj.objectoptions,oo_has_constructor);
  226. end;
  227. end;
  228. procedure implement_anon_inherited(pd: tprocdef);
  229. var
  230. str: ansistring;
  231. isclassmethod: boolean;
  232. begin
  233. isclassmethod:=
  234. (po_classmethod in pd.procoptions) and
  235. not(pd.proctypeoption in [potype_constructor,potype_destructor]);
  236. str:='begin inherited end;';
  237. str_parse_method_impl(str,pd,isclassmethod);
  238. end;
  239. procedure implement_jvm_clone(pd: tprocdef);
  240. var
  241. struct: tabstractrecorddef;
  242. str: ansistring;
  243. i: longint;
  244. sym: tsym;
  245. fsym: tfieldvarsym;
  246. begin
  247. if not(pd.struct.typ in [recorddef,objectdef]) then
  248. internalerror(2011032802);
  249. struct:=pd.struct;
  250. { anonymous record types must get an artificial name, so we can generate
  251. a typecast at the scanner level }
  252. if (struct.typ=recorddef) and
  253. not assigned(struct.typesym) then
  254. internalerror(2011032812);
  255. { the inherited clone will already copy all fields in a shallow way ->
  256. copy records/regular arrays in a regular way }
  257. str:='type _fpc_ptrt = ^'+struct.typesym.realname+'; begin clone:=inherited;';
  258. for i:=0 to struct.symtable.symlist.count-1 do
  259. begin
  260. sym:=tsym(struct.symtable.symlist[i]);
  261. if (sym.typ=fieldvarsym) then
  262. begin
  263. fsym:=tfieldvarsym(sym);
  264. if (fsym.vardef.typ=recorddef) or
  265. ((fsym.vardef.typ=arraydef) and
  266. not is_dynamic_array(fsym.vardef)) or
  267. ((fsym.vardef.typ=setdef) and
  268. not is_smallset(fsym.vardef)) then
  269. str:=str+'_fpc_ptrt(clone)^.&'+fsym.realname+':='+fsym.realname+';';
  270. end;
  271. end;
  272. str:=str+'end;';
  273. str_parse_method_impl(str,pd,false);
  274. end;
  275. procedure implement_record_deepcopy(pd: tprocdef);
  276. var
  277. struct: tabstractrecorddef;
  278. str: ansistring;
  279. i: longint;
  280. sym: tsym;
  281. fsym: tfieldvarsym;
  282. begin
  283. if not(pd.struct.typ in [recorddef,objectdef]) then
  284. internalerror(2011032810);
  285. struct:=pd.struct;
  286. { anonymous record types must get an artificial name, so we can generate
  287. a typecast at the scanner level }
  288. if (struct.typ=recorddef) and
  289. not assigned(struct.typesym) then
  290. internalerror(2011032811);
  291. { copy all fields }
  292. str:='begin ';
  293. for i:=0 to struct.symtable.symlist.count-1 do
  294. begin
  295. sym:=tsym(struct.symtable.symlist[i]);
  296. if (sym.typ=fieldvarsym) then
  297. begin
  298. fsym:=tfieldvarsym(sym);
  299. str:=str+'result.&'+fsym.realname+':='+fsym.realname+';';
  300. end;
  301. end;
  302. str:=str+'end;';
  303. str_parse_method_impl(str,pd,false);
  304. end;
  305. procedure implement_empty(pd: tprocdef);
  306. var
  307. str: ansistring;
  308. isclassmethod: boolean;
  309. begin
  310. isclassmethod:=
  311. (po_classmethod in pd.procoptions) and
  312. not(pd.proctypeoption in [potype_constructor,potype_destructor]);
  313. str:='begin end;';
  314. str_parse_method_impl(str,pd,isclassmethod);
  315. end;
  316. procedure add_synthetic_method_implementations_for_struct(struct: tabstractrecorddef);
  317. var
  318. i : longint;
  319. def : tdef;
  320. pd : tprocdef;
  321. begin
  322. for i:=0 to struct.symtable.deflist.count-1 do
  323. begin
  324. def:=tdef(struct.symtable.deflist[i]);
  325. if (def.typ<>procdef) then
  326. continue;
  327. pd:=tprocdef(def);
  328. case pd.synthetickind of
  329. tsk_none:
  330. ;
  331. tsk_anon_inherited:
  332. implement_anon_inherited(pd);
  333. tsk_jvm_clone:
  334. implement_jvm_clone(pd);
  335. tsk_record_deepcopy:
  336. implement_record_deepcopy(pd);
  337. tsk_empty,
  338. { special handling for this one is done in tnodeutils.wrap_proc_body }
  339. tsk_tcinit:
  340. implement_empty(pd);
  341. else
  342. internalerror(2011032801);
  343. end;
  344. end;
  345. end;
  346. procedure add_synthetic_method_implementations(st: tsymtable);
  347. var
  348. i: longint;
  349. def: tdef;
  350. sstate: tscannerstate;
  351. begin
  352. { only necessary for the JVM target currently }
  353. if not (target_info.system in [system_jvm_java32]) then
  354. exit;
  355. sstate.valid:=false;
  356. for i:=0 to st.deflist.count-1 do
  357. begin
  358. def:=tdef(st.deflist[i]);
  359. if (def.typ=procdef) and
  360. assigned(tprocdef(def).localst) and
  361. { not true for the "main" procedure, whose localsymtable is the staticsymtable }
  362. (tprocdef(def).localst.symtabletype=localsymtable) then
  363. add_synthetic_method_implementations(tprocdef(def).localst)
  364. else if (is_javaclass(def) and
  365. not(oo_is_external in tobjectdef(def).objectoptions)) or
  366. (def.typ=recorddef) then
  367. begin
  368. if not sstate.valid then
  369. replace_scanner('synthetic_impl',sstate);
  370. add_synthetic_method_implementations_for_struct(tabstractrecorddef(def));
  371. { also complete nested types }
  372. add_synthetic_method_implementations(tabstractrecorddef(def).symtable);
  373. end;
  374. end;
  375. restore_scanner(sstate);
  376. end;
  377. procedure finish_copied_procdef(var pd: tprocdef; const realname: string; newparentst: tsymtable; newstruct: tabstractrecorddef);
  378. var
  379. sym: tsym;
  380. parasym: tparavarsym;
  381. ps: tprocsym;
  382. stname: string;
  383. i: longint;
  384. begin
  385. { associate the procdef with a procsym in the owner }
  386. if not(pd.proctypeoption in [potype_class_constructor,potype_class_destructor]) then
  387. stname:=upper(realname)
  388. else
  389. stname:=lower(realname);
  390. sym:=tsym(newparentst.find(stname));
  391. if assigned(sym) then
  392. begin
  393. if sym.typ<>procsym then
  394. internalerror(2011040601);
  395. ps:=tprocsym(sym);
  396. end
  397. else
  398. begin
  399. ps:=tprocsym.create(realname);
  400. newparentst.insert(ps);
  401. end;
  402. pd.procsym:=ps;
  403. pd.struct:=newstruct;
  404. { in case of methods, replace the special parameter types with new ones }
  405. if assigned(newstruct) then
  406. begin
  407. symtablestack.push(pd.parast);
  408. for i:=0 to pd.paras.count-1 do
  409. begin
  410. parasym:=tparavarsym(pd.paras[i]);
  411. if vo_is_self in parasym.varoptions then
  412. begin
  413. if parasym.vardef.typ=classrefdef then
  414. parasym.vardef:=tclassrefdef.create(newstruct)
  415. else
  416. parasym.vardef:=newstruct;
  417. end
  418. end;
  419. { also fix returndef in case of a constructor }
  420. if pd.proctypeoption=potype_constructor then
  421. pd.returndef:=newstruct;
  422. symtablestack.pop(pd.parast);
  423. end;
  424. proc_add_definition(pd);
  425. end;
  426. procedure build_parentfpstruct(pd: tprocdef);
  427. var
  428. nestedvars: tsym;
  429. nestedvarsst: tsymtable;
  430. pnestedvarsdef,
  431. nestedvarsdef: tdef;
  432. old_symtablestack: tsymtablestack;
  433. begin
  434. { make sure the defs are not registered in the current symtablestack,
  435. because they may be for a parent procdef (changeowner does remove a def
  436. from the symtable in which it was originally created, so that by itself
  437. is not enough) }
  438. old_symtablestack:=symtablestack;
  439. symtablestack:=old_symtablestack.getcopyuntil(current_module.localsymtable);
  440. { create struct to hold local variables and parameters that are
  441. accessed from within nested routines }
  442. nestedvarsst:=trecordsymtable.create(current_module.realmodulename^+'$$_fpc_nestedvars$'+tostr(pd.defid),current_settings.alignment.localalignmax);
  443. nestedvarsdef:=trecorddef.create(nestedvarsst.name^,nestedvarsst);
  444. {$ifdef jvm}
  445. jvm_guarantee_record_typesym(nestedvarsdef,nestedvarsdef.owner);
  446. { don't add clone/FpcDeepCopy, because the field names are not all
  447. representable in source form and we don't need them anyway }
  448. symtablestack.push(trecorddef(nestedvarsdef).symtable);
  449. maybe_add_public_default_java_constructor(trecorddef(nestedvarsdef));
  450. symtablestack.pop(trecorddef(nestedvarsdef).symtable);
  451. {$endif}
  452. symtablestack.free;
  453. symtablestack:=old_symtablestack.getcopyuntil(pd.localst);
  454. pnestedvarsdef:=tpointerdef.create(nestedvarsdef);
  455. nestedvars:=tlocalvarsym.create('$nestedvars',vs_var,nestedvarsdef,[]);
  456. pd.localst.insert(nestedvars);
  457. pd.parentfpstruct:=nestedvars;
  458. pd.parentfpstructptrtype:=pnestedvarsdef;
  459. pd.parentfpinitblock:=cblocknode.create(nil);
  460. symtablestack.free;
  461. symtablestack:=old_symtablestack;
  462. end;
  463. function maybe_add_sym_to_parentfpstruct(pd: tprocdef; sym: tsym; vardef: tdef; addrparam: boolean): tsym;
  464. var
  465. fieldvardef,
  466. nestedvarsdef: tdef;
  467. nestedvarsst: tsymtable;
  468. initcode: tnode;
  469. old_filepos: tfileposinfo;
  470. begin
  471. nestedvarsdef:=tlocalvarsym(pd.parentfpstruct).vardef;
  472. result:=search_struct_member(trecorddef(nestedvarsdef),sym.name);
  473. if not assigned(result) then
  474. begin
  475. { mark that this symbol is mirrored in the parentfpstruct }
  476. tabstractnormalvarsym(sym).inparentfpstruct:=true;
  477. { add field to the struct holding all locals accessed
  478. by nested routines }
  479. nestedvarsst:=trecorddef(nestedvarsdef).symtable;
  480. { indicate whether or not this is a var/out/constref/... parameter }
  481. if addrparam then
  482. fieldvardef:=tpointerdef.create(vardef)
  483. else
  484. fieldvardef:=vardef;
  485. result:=tfieldvarsym.create(sym.realname,vs_value,fieldvardef,[]);
  486. if nestedvarsst.symlist.count=0 then
  487. include(tfieldvarsym(result).varoptions,vo_is_first_field);
  488. nestedvarsst.insert(result);
  489. trecordsymtable(nestedvarsst).addfield(tfieldvarsym(result),vis_public);
  490. { add initialization with original value if it's a parameter }
  491. if (sym.typ=paravarsym) then
  492. begin
  493. old_filepos:=current_filepos;
  494. fillchar(current_filepos,sizeof(current_filepos),0);
  495. initcode:=cloadnode.create(sym,sym.owner);
  496. { indicate that this load should not be transformed into a load
  497. from the parentfpstruct, but instead should load the original
  498. value }
  499. include(initcode.flags,nf_internal);
  500. { in case it's a var/out/constref parameter, store the address of the
  501. parameter in the struct }
  502. if addrparam then
  503. begin
  504. initcode:=caddrnode.create_internal(initcode);
  505. include(initcode.flags,nf_typedaddr);
  506. end;
  507. initcode:=cassignmentnode.create(
  508. csubscriptnode.create(result,cloadnode.create(pd.parentfpstruct,pd.parentfpstruct.owner)),
  509. initcode);
  510. tblocknode(pd.parentfpinitblock).left:=cstatementnode.create
  511. (initcode,tblocknode(pd.parentfpinitblock).left);
  512. current_filepos:=old_filepos;
  513. end;
  514. end;
  515. end;
  516. procedure redirect_parentfpstruct_local_syms(pd: tprocdef);
  517. var
  518. nestedvarsdef: trecorddef;
  519. sl: tpropaccesslist;
  520. fsym,
  521. lsym,
  522. aliassym: tsym;
  523. i: longint;
  524. begin
  525. nestedvarsdef:=trecorddef(tlocalvarsym(pd.parentfpstruct).vardef);
  526. for i:=0 to nestedvarsdef.symtable.symlist.count-1 do
  527. begin
  528. fsym:=tsym(nestedvarsdef.symtable.symlist[i]);
  529. if fsym.typ<>fieldvarsym then
  530. continue;
  531. lsym:=tsym(pd.localst.find(fsym.name));
  532. if not assigned(lsym) then
  533. lsym:=tsym(pd.parast.find(fsym.name));
  534. if not assigned(lsym) then
  535. internalerror(2011060408);
  536. { add an absolute variable that redirects to the field }
  537. sl:=tpropaccesslist.create;
  538. sl.addsym(sl_load,pd.parentfpstruct);
  539. sl.addsym(sl_subscript,tfieldvarsym(fsym));
  540. aliassym:=tabsolutevarsym.create_ref(lsym.name,tfieldvarsym(fsym).vardef,sl);
  541. { hide the original variable (can't delete, because there
  542. may be other loadnodes that reference it)
  543. -- only for locals; hiding parameters changes the
  544. function signature }
  545. if lsym.typ<>paravarsym then
  546. hidesym(lsym);
  547. { insert the absolute variable in the localst of the
  548. routine; ignore duplicates, because this will also check the
  549. parasymtable and we want to override parameters with our local
  550. versions }
  551. pd.localst.insert(aliassym,false);
  552. end;
  553. end;
  554. function find_sym_in_parentfpstruct(pd: tprocdef; sym: tsym): tsym;
  555. var
  556. nestedvarsdef: tdef;
  557. begin
  558. nestedvarsdef:=tlocalvarsym(pd.parentfpstruct).vardef;
  559. result:=search_struct_member(trecorddef(nestedvarsdef),sym.name);
  560. end;
  561. procedure finish_parentfpstruct(pd: tprocdef);
  562. begin
  563. trecordsymtable(trecorddef(tlocalvarsym(pd.parentfpstruct).vardef).symtable).addalignmentpadding;
  564. end;
  565. end.