symcreat.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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);
  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);
  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. finish_copied_procdef(childpd,parentpd.procsym.realname,obj.symtable,obj);
  220. exclude(childpd.procoptions,po_external);
  221. include(childpd.procoptions,po_overload);
  222. childpd.synthetickind:=tsk_anon_inherited;
  223. include(obj.objectoptions,oo_has_constructor);
  224. end;
  225. end;
  226. procedure implement_anon_inherited(pd: tprocdef);
  227. var
  228. str: ansistring;
  229. isclassmethod: boolean;
  230. begin
  231. isclassmethod:=
  232. (po_classmethod in pd.procoptions) and
  233. not(pd.proctypeoption in [potype_constructor,potype_destructor]);
  234. str:='begin inherited end;';
  235. str_parse_method_impl(str,pd,isclassmethod);
  236. end;
  237. procedure implement_jvm_clone(pd: tprocdef);
  238. var
  239. struct: tabstractrecorddef;
  240. str: ansistring;
  241. i: longint;
  242. sym: tsym;
  243. fsym: tfieldvarsym;
  244. begin
  245. if not(pd.struct.typ in [recorddef,objectdef]) then
  246. internalerror(2011032802);
  247. struct:=pd.struct;
  248. { anonymous record types must get an artificial name, so we can generate
  249. a typecast at the scanner level }
  250. if (struct.typ=recorddef) and
  251. not assigned(struct.typesym) then
  252. internalerror(2011032812);
  253. { the inherited clone will already copy all fields in a shallow way ->
  254. copy records/regular arrays in a regular way }
  255. str:='type _fpc_ptrt = ^'+struct.typesym.realname+'; begin clone:=inherited;';
  256. for i:=0 to struct.symtable.symlist.count-1 do
  257. begin
  258. sym:=tsym(struct.symtable.symlist[i]);
  259. if (sym.typ=fieldvarsym) then
  260. begin
  261. fsym:=tfieldvarsym(sym);
  262. if (fsym.vardef.typ=recorddef) or
  263. ((fsym.vardef.typ=arraydef) and
  264. not is_dynamic_array(fsym.vardef)) or
  265. ((fsym.vardef.typ=setdef) and
  266. not is_smallset(fsym.vardef)) then
  267. str:=str+'_fpc_ptrt(clone)^.&'+fsym.realname+':='+fsym.realname+';';
  268. end;
  269. end;
  270. str:=str+'end;';
  271. str_parse_method_impl(str,pd,false);
  272. end;
  273. procedure implement_record_deepcopy(pd: tprocdef);
  274. var
  275. struct: tabstractrecorddef;
  276. str: ansistring;
  277. i: longint;
  278. sym: tsym;
  279. fsym: tfieldvarsym;
  280. begin
  281. if not(pd.struct.typ in [recorddef,objectdef]) then
  282. internalerror(2011032810);
  283. struct:=pd.struct;
  284. { anonymous record types must get an artificial name, so we can generate
  285. a typecast at the scanner level }
  286. if (struct.typ=recorddef) and
  287. not assigned(struct.typesym) then
  288. internalerror(2011032811);
  289. { copy all fields }
  290. str:='begin ';
  291. for i:=0 to struct.symtable.symlist.count-1 do
  292. begin
  293. sym:=tsym(struct.symtable.symlist[i]);
  294. if (sym.typ=fieldvarsym) then
  295. begin
  296. fsym:=tfieldvarsym(sym);
  297. str:=str+'result.&'+fsym.realname+':='+fsym.realname+';';
  298. end;
  299. end;
  300. str:=str+'end;';
  301. str_parse_method_impl(str,pd,false);
  302. end;
  303. procedure implement_empty(pd: tprocdef);
  304. var
  305. str: ansistring;
  306. isclassmethod: boolean;
  307. begin
  308. isclassmethod:=
  309. (po_classmethod in pd.procoptions) and
  310. not(pd.proctypeoption in [potype_constructor,potype_destructor]);
  311. str:='begin end;';
  312. str_parse_method_impl(str,pd,isclassmethod);
  313. end;
  314. procedure add_synthetic_method_implementations_for_struct(struct: tabstractrecorddef);
  315. var
  316. i : longint;
  317. def : tdef;
  318. pd : tprocdef;
  319. begin
  320. for i:=0 to struct.symtable.deflist.count-1 do
  321. begin
  322. def:=tdef(struct.symtable.deflist[i]);
  323. if (def.typ<>procdef) then
  324. continue;
  325. pd:=tprocdef(def);
  326. case pd.synthetickind of
  327. tsk_none:
  328. ;
  329. tsk_anon_inherited:
  330. implement_anon_inherited(pd);
  331. tsk_jvm_clone:
  332. implement_jvm_clone(pd);
  333. tsk_record_deepcopy:
  334. implement_record_deepcopy(pd);
  335. tsk_empty,
  336. { special handling for this one is done in tnodeutils.wrap_proc_body }
  337. tsk_tcinit:
  338. implement_empty(pd);
  339. else
  340. internalerror(2011032801);
  341. end;
  342. end;
  343. end;
  344. procedure add_synthetic_method_implementations(st: tsymtable);
  345. var
  346. i: longint;
  347. def: tdef;
  348. sstate: tscannerstate;
  349. begin
  350. { only necessary for the JVM target currently }
  351. if not (target_info.system in [system_jvm_java32]) then
  352. exit;
  353. sstate.valid:=false;
  354. for i:=0 to st.deflist.count-1 do
  355. begin
  356. def:=tdef(st.deflist[i]);
  357. if (def.typ=procdef) and
  358. assigned(tprocdef(def).localst) and
  359. { not true for the "main" procedure, whose localsymtable is the staticsymtable }
  360. (tprocdef(def).localst.symtabletype=localsymtable) then
  361. add_synthetic_method_implementations(tprocdef(def).localst)
  362. else if (is_javaclass(def) and
  363. not(oo_is_external in tobjectdef(def).objectoptions)) or
  364. (def.typ=recorddef) then
  365. begin
  366. if not sstate.valid then
  367. replace_scanner('synthetic_impl',sstate);
  368. add_synthetic_method_implementations_for_struct(tabstractrecorddef(def));
  369. { also complete nested types }
  370. add_synthetic_method_implementations(tabstractrecorddef(def).symtable);
  371. end;
  372. end;
  373. restore_scanner(sstate);
  374. end;
  375. procedure finish_copied_procdef(var pd: tprocdef; const realname: string; newparentst: tsymtable; newstruct: tabstractrecorddef);
  376. var
  377. sym: tsym;
  378. parasym: tparavarsym;
  379. ps: tprocsym;
  380. stname: string;
  381. i: longint;
  382. begin
  383. { associate the procdef with a procsym in the owner }
  384. if not(pd.proctypeoption in [potype_class_constructor,potype_class_destructor]) then
  385. stname:=upper(realname)
  386. else
  387. stname:=lower(realname);
  388. sym:=tsym(newparentst.find(stname));
  389. if assigned(sym) then
  390. begin
  391. if sym.typ<>procsym then
  392. internalerror(2011040601);
  393. ps:=tprocsym(sym);
  394. end
  395. else
  396. begin
  397. ps:=tprocsym.create(realname);
  398. newparentst.insert(ps);
  399. end;
  400. pd.procsym:=ps;
  401. pd.struct:=newstruct;
  402. { in case of methods, replace the special parameter types with new ones }
  403. if assigned(newstruct) then
  404. begin
  405. symtablestack.push(pd.parast);
  406. for i:=0 to pd.paras.count-1 do
  407. begin
  408. parasym:=tparavarsym(pd.paras[i]);
  409. if vo_is_self in parasym.varoptions then
  410. begin
  411. if parasym.vardef.typ=classrefdef then
  412. parasym.vardef:=tclassrefdef.create(newstruct)
  413. else
  414. parasym.vardef:=newstruct;
  415. end
  416. end;
  417. { also fix returndef in case of a constructor }
  418. if pd.proctypeoption=potype_constructor then
  419. pd.returndef:=newstruct;
  420. symtablestack.pop(pd.parast);
  421. end;
  422. proc_add_definition(pd);
  423. end;
  424. procedure build_parentfpstruct(pd: tprocdef);
  425. var
  426. nestedvars: tsym;
  427. nestedvarsst: tsymtable;
  428. pnestedvarsdef,
  429. nestedvarsdef: tdef;
  430. old_symtablestack: tsymtablestack;
  431. begin
  432. { make sure the defs are not registered in the current symtablestack,
  433. because they may be for a parent procdef (changeowner does remove a def
  434. from the symtable in which it was originally created, so that by itself
  435. is not enough) }
  436. old_symtablestack:=symtablestack;
  437. symtablestack:=old_symtablestack.getcopyuntil(current_module.localsymtable);
  438. { create struct to hold local variables and parameters that are
  439. accessed from within nested routines }
  440. nestedvarsst:=trecordsymtable.create(current_module.realmodulename^+'$$_fpc_nestedvars$'+tostr(pd.procsym.symid),current_settings.alignment.localalignmax);
  441. nestedvarsdef:=trecorddef.create(nestedvarsst.name^,nestedvarsst);
  442. {$ifdef jvm}
  443. jvm_guarantee_record_typesym(nestedvarsdef,nestedvarsdef.owner);
  444. { don't add clone/FpcDeepCopy, because the field names are not all
  445. representable in source form and we don't need them anyway }
  446. symtablestack.push(trecorddef(nestedvarsdef).symtable);
  447. maybe_add_public_default_java_constructor(trecorddef(nestedvarsdef));
  448. symtablestack.pop(trecorddef(nestedvarsdef).symtable);
  449. {$endif}
  450. symtablestack.free;
  451. symtablestack:=old_symtablestack.getcopyuntil(pd.localst);
  452. pnestedvarsdef:=tpointerdef.create(nestedvarsdef);
  453. nestedvars:=tlocalvarsym.create('$nestedvars',vs_var,nestedvarsdef,[]);
  454. pd.localst.insert(nestedvars);
  455. pd.parentfpstruct:=nestedvars;
  456. pd.parentfpstructptrtype:=pnestedvarsdef;
  457. pd.parentfpinitblock:=cblocknode.create(nil);
  458. symtablestack.free;
  459. symtablestack:=old_symtablestack;
  460. end;
  461. function maybe_add_sym_to_parentfpstruct(pd: tprocdef; sym: tsym; vardef: tdef; addrparam: boolean): tsym;
  462. var
  463. fieldvardef,
  464. nestedvarsdef: tdef;
  465. nestedvarsst: tsymtable;
  466. initcode: tnode;
  467. old_filepos: tfileposinfo;
  468. begin
  469. nestedvarsdef:=tlocalvarsym(pd.parentfpstruct).vardef;
  470. result:=search_struct_member(trecorddef(nestedvarsdef),sym.name);
  471. if not assigned(result) then
  472. begin
  473. { mark that this symbol is mirrored in the parentfpstruct }
  474. tabstractnormalvarsym(sym).inparentfpstruct:=true;
  475. { add field to the struct holding all locals accessed
  476. by nested routines }
  477. nestedvarsst:=trecorddef(nestedvarsdef).symtable;
  478. { indicate whether or not this is a var/out/constref/... parameter }
  479. if addrparam then
  480. fieldvardef:=tpointerdef.create(vardef)
  481. else
  482. fieldvardef:=vardef;
  483. result:=tfieldvarsym.create(sym.realname,vs_value,fieldvardef,[]);
  484. if nestedvarsst.symlist.count=0 then
  485. include(tfieldvarsym(result).varoptions,vo_is_first_field);
  486. nestedvarsst.insert(result);
  487. trecordsymtable(nestedvarsst).addfield(tfieldvarsym(result),vis_public);
  488. { add initialization with original value if it's a parameter }
  489. if (sym.typ=paravarsym) then
  490. begin
  491. old_filepos:=current_filepos;
  492. fillchar(current_filepos,sizeof(current_filepos),0);
  493. initcode:=cloadnode.create(sym,sym.owner);
  494. { indicate that this load should not be transformed into a load
  495. from the parentfpstruct, but instead should load the original
  496. value }
  497. include(initcode.flags,nf_internal);
  498. { in case it's a var/out/constref parameter, store the address of the
  499. parameter in the struct }
  500. if addrparam then
  501. begin
  502. initcode:=caddrnode.create_internal(initcode);
  503. include(initcode.flags,nf_typedaddr);
  504. end;
  505. initcode:=cassignmentnode.create(
  506. csubscriptnode.create(result,cloadnode.create(pd.parentfpstruct,pd.parentfpstruct.owner)),
  507. initcode);
  508. tblocknode(pd.parentfpinitblock).left:=cstatementnode.create
  509. (initcode,tblocknode(pd.parentfpinitblock).left);
  510. current_filepos:=old_filepos;
  511. end;
  512. end;
  513. end;
  514. procedure redirect_parentfpstruct_local_syms(pd: tprocdef);
  515. var
  516. nestedvarsdef: trecorddef;
  517. sl: tpropaccesslist;
  518. fsym,
  519. lsym,
  520. aliassym: tsym;
  521. i: longint;
  522. begin
  523. nestedvarsdef:=trecorddef(tlocalvarsym(pd.parentfpstruct).vardef);
  524. for i:=0 to nestedvarsdef.symtable.symlist.count-1 do
  525. begin
  526. fsym:=tsym(nestedvarsdef.symtable.symlist[i]);
  527. if fsym.typ<>fieldvarsym then
  528. continue;
  529. lsym:=tsym(pd.localst.find(fsym.name));
  530. if not assigned(lsym) then
  531. lsym:=tsym(pd.parast.find(fsym.name));
  532. if not assigned(lsym) then
  533. internalerror(2011060408);
  534. { add an absolute variable that redirects to the field }
  535. sl:=tpropaccesslist.create;
  536. sl.addsym(sl_load,pd.parentfpstruct);
  537. sl.addsym(sl_subscript,tfieldvarsym(fsym));
  538. aliassym:=tabsolutevarsym.create_ref(lsym.name,tfieldvarsym(fsym).vardef,sl);
  539. { hide the original variable (can't delete, because there
  540. may be other loadnodes that reference it)
  541. -- only for locals; hiding parameters changes the
  542. function signature }
  543. if lsym.typ<>paravarsym then
  544. hidesym(lsym);
  545. { insert the absolute variable in the localst of the
  546. routine; ignore duplicates, because this will also check the
  547. parasymtable and we want to override parameters with our local
  548. versions }
  549. pd.localst.insert(aliassym,false);
  550. end;
  551. end;
  552. function find_sym_in_parentfpstruct(pd: tprocdef; sym: tsym): tsym;
  553. var
  554. nestedvarsdef: tdef;
  555. begin
  556. nestedvarsdef:=tlocalvarsym(pd.parentfpstruct).vardef;
  557. result:=search_struct_member(trecorddef(nestedvarsdef),sym.name);
  558. end;
  559. procedure finish_parentfpstruct(pd: tprocdef);
  560. begin
  561. trecordsymtable(trecorddef(tlocalvarsym(pd.parentfpstruct).vardef).symtable).addalignmentpadding;
  562. end;
  563. end.