nld.pas 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. Type checking and register allocation for load/assignment nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nld;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. {$ifdef state_tracking}
  23. nstate,
  24. {$endif}
  25. symconst,symbase,symtype,symsym,symdef;
  26. type
  27. Trttidatatype=(rdt_normal,rdt_ord2str,rdt_str2ord);
  28. tloadnode = class(tunarynode)
  29. protected
  30. procdef : tprocdef;
  31. procdefderef : tderef;
  32. public
  33. symtableentry : tsym;
  34. symtableentryderef : tderef;
  35. symtable : TSymtable;
  36. constructor create(v : tsym;st : TSymtable);virtual;
  37. constructor create_procvar(v : tsym;d:tprocdef;st : TSymtable);virtual;
  38. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  39. procedure ppuwrite(ppufile:tcompilerppufile);override;
  40. procedure buildderefimpl;override;
  41. procedure derefimpl;override;
  42. procedure set_mp(p:tnode);
  43. function is_addr_param_load:boolean;
  44. function dogetcopy : tnode;override;
  45. function pass_1 : tnode;override;
  46. function pass_typecheck:tnode;override;
  47. procedure mark_write;override;
  48. function docompare(p: tnode): boolean; override;
  49. procedure printnodedata(var t:text);override;
  50. procedure setprocdef(p : tprocdef);
  51. end;
  52. tloadnodeclass = class of tloadnode;
  53. { different assignment types }
  54. tassigntype = (at_normal,at_plus,at_minus,at_star,at_slash);
  55. tassignmentnode = class(tbinarynode)
  56. assigntype : tassigntype;
  57. constructor create(l,r : tnode);virtual;
  58. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  59. procedure ppuwrite(ppufile:tcompilerppufile);override;
  60. function dogetcopy : tnode;override;
  61. function pass_1 : tnode;override;
  62. function pass_typecheck:tnode;override;
  63. {$ifdef state_tracking}
  64. function track_state_pass(exec_known:boolean):boolean;override;
  65. {$endif state_tracking}
  66. function docompare(p: tnode): boolean; override;
  67. end;
  68. tassignmentnodeclass = class of tassignmentnode;
  69. tarrayconstructorrangenode = class(tbinarynode)
  70. constructor create(l,r : tnode);virtual;
  71. function pass_1 : tnode;override;
  72. function pass_typecheck:tnode;override;
  73. end;
  74. tarrayconstructorrangenodeclass = class of tarrayconstructorrangenode;
  75. tarrayconstructornode = class(tbinarynode)
  76. constructor create(l,r : tnode);virtual;
  77. function dogetcopy : tnode;override;
  78. function pass_1 : tnode;override;
  79. function pass_typecheck:tnode;override;
  80. function docompare(p: tnode): boolean; override;
  81. procedure force_type(def:tdef);
  82. procedure insert_typeconvs;
  83. end;
  84. tarrayconstructornodeclass = class of tarrayconstructornode;
  85. ttypenode = class(tnode)
  86. allowed : boolean;
  87. typedef : tdef;
  88. typedefderef : tderef;
  89. constructor create(def:tdef);virtual;
  90. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  91. procedure ppuwrite(ppufile:tcompilerppufile);override;
  92. procedure buildderefimpl;override;
  93. procedure derefimpl;override;
  94. function pass_1 : tnode;override;
  95. function pass_typecheck:tnode;override;
  96. function dogetcopy : tnode;override;
  97. function docompare(p: tnode): boolean; override;
  98. end;
  99. ttypenodeclass = class of ttypenode;
  100. trttinode = class(tnode)
  101. l1,l2 : longint;
  102. rttitype : trttitype;
  103. rttidef : tstoreddef;
  104. rttidefderef : tderef;
  105. rttidatatype : Trttidatatype;
  106. constructor create(def:tstoreddef;rt:trttitype;dt:Trttidatatype);virtual;
  107. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  108. procedure ppuwrite(ppufile:tcompilerppufile);override;
  109. procedure buildderefimpl;override;
  110. procedure derefimpl;override;
  111. function dogetcopy : tnode;override;
  112. function pass_1 : tnode;override;
  113. function pass_typecheck:tnode;override;
  114. function docompare(p: tnode): boolean; override;
  115. end;
  116. trttinodeclass = class of trttinode;
  117. var
  118. cloadnode : tloadnodeclass;
  119. cassignmentnode : tassignmentnodeclass;
  120. carrayconstructorrangenode : tarrayconstructorrangenodeclass;
  121. carrayconstructornode : tarrayconstructornodeclass;
  122. ctypenode : ttypenodeclass;
  123. crttinode : trttinodeclass;
  124. { Current assignment node }
  125. aktassignmentnode : tassignmentnode;
  126. implementation
  127. uses
  128. cutils,verbose,globtype,globals,systems,
  129. symnot,
  130. defutil,defcmp,
  131. htypechk,pass_1,procinfo,paramgr,
  132. ncon,ninl,ncnv,nmem,ncal,nutils,nbas,
  133. cgobj,cgbase
  134. ;
  135. {*****************************************************************************
  136. TLOADNODE
  137. *****************************************************************************}
  138. constructor tloadnode.create(v : tsym;st : TSymtable);
  139. begin
  140. inherited create(loadn,nil);
  141. if not assigned(v) then
  142. internalerror(200108121);
  143. symtableentry:=v;
  144. symtable:=st;
  145. procdef:=nil;
  146. end;
  147. constructor tloadnode.create_procvar(v : tsym;d:tprocdef;st : TSymtable);
  148. begin
  149. inherited create(loadn,nil);
  150. if not assigned(v) then
  151. internalerror(200108121);
  152. symtableentry:=v;
  153. symtable:=st;
  154. procdef:=d;
  155. end;
  156. constructor tloadnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  157. begin
  158. inherited ppuload(t,ppufile);
  159. ppufile.getderef(symtableentryderef);
  160. symtable:=nil;
  161. ppufile.getderef(procdefderef);
  162. end;
  163. procedure tloadnode.ppuwrite(ppufile:tcompilerppufile);
  164. begin
  165. inherited ppuwrite(ppufile);
  166. ppufile.putderef(symtableentryderef);
  167. ppufile.putderef(procdefderef);
  168. end;
  169. procedure tloadnode.buildderefimpl;
  170. begin
  171. inherited buildderefimpl;
  172. symtableentryderef.build(symtableentry);
  173. procdefderef.build(procdef);
  174. end;
  175. procedure tloadnode.derefimpl;
  176. begin
  177. inherited derefimpl;
  178. symtableentry:=tsym(symtableentryderef.resolve);
  179. symtable:=symtableentry.owner;
  180. procdef:=tprocdef(procdefderef.resolve);
  181. end;
  182. procedure tloadnode.set_mp(p:tnode);
  183. begin
  184. { typen nodes should not be set }
  185. if p.nodetype=typen then
  186. internalerror(200301042);
  187. left:=p;
  188. end;
  189. function tloadnode.dogetcopy : tnode;
  190. var
  191. n : tloadnode;
  192. begin
  193. n:=tloadnode(inherited dogetcopy);
  194. n.symtable:=symtable;
  195. n.symtableentry:=symtableentry;
  196. n.procdef:=procdef;
  197. result:=n;
  198. end;
  199. function tloadnode.is_addr_param_load:boolean;
  200. begin
  201. result:=(symtable.symtabletype=parasymtable) and
  202. (symtableentry.typ=paravarsym) and
  203. not(vo_has_local_copy in tparavarsym(symtableentry).varoptions) and
  204. not(nf_load_self_pointer in flags) and
  205. paramanager.push_addr_param(tparavarsym(symtableentry).varspez,tparavarsym(symtableentry).vardef,tprocdef(symtable.defowner).proccalloption);
  206. end;
  207. function tloadnode.pass_typecheck:tnode;
  208. begin
  209. result:=nil;
  210. case symtableentry.typ of
  211. absolutevarsym :
  212. resultdef:=tabsolutevarsym(symtableentry).vardef;
  213. constsym:
  214. begin
  215. if tconstsym(symtableentry).consttyp=constresourcestring then
  216. resultdef:=cansistringtype
  217. else
  218. internalerror(22799);
  219. end;
  220. staticvarsym :
  221. begin
  222. tabstractvarsym(symtableentry).IncRefCountBy(1);
  223. { static variables referenced in procedures or from finalization,
  224. variable needs to be in memory.
  225. It is too hard and the benefit is too small to detect whether a
  226. variable is only used in the finalization to add support for it (PFV) }
  227. if assigned(current_procinfo) and
  228. (symtable.symtabletype=staticsymtable) and
  229. (
  230. (symtable.symtablelevel<>current_procinfo.procdef.localst.symtablelevel) or
  231. (current_procinfo.procdef.proctypeoption=potype_unitfinalize)
  232. ) then
  233. make_not_regable(self,[ra_addr_taken]);
  234. resultdef:=tabstractvarsym(symtableentry).vardef;
  235. end;
  236. paravarsym,
  237. localvarsym :
  238. begin
  239. tabstractvarsym(symtableentry).IncRefCountBy(1);
  240. { Nested variable? The we need to load the framepointer of
  241. the parent procedure }
  242. if assigned(current_procinfo) and
  243. (symtable.symtabletype in [localsymtable,parasymtable]) and
  244. (symtable.symtablelevel<>current_procinfo.procdef.parast.symtablelevel) then
  245. begin
  246. if assigned(left) then
  247. internalerror(200309289);
  248. left:=cloadparentfpnode.create(tprocdef(symtable.defowner));
  249. { we can't inline the referenced parent procedure }
  250. exclude(tprocdef(symtable.defowner).procoptions,po_inline);
  251. { reference in nested procedures, variable needs to be in memory }
  252. { and behaves as if its address escapes its parent block }
  253. make_not_regable(self,[ra_addr_taken]);
  254. end;
  255. { fix self type which is declared as voidpointer in the
  256. definition }
  257. if vo_is_self in tabstractvarsym(symtableentry).varoptions then
  258. begin
  259. resultdef:=tprocdef(symtableentry.owner.defowner)._class;
  260. if (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) or
  261. (po_staticmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
  262. resultdef:=tclassrefdef.create(resultdef)
  263. else if is_object(resultdef) and
  264. (nf_load_self_pointer in flags) then
  265. resultdef:=tpointerdef.create(resultdef);
  266. end
  267. else if vo_is_vmt in tabstractvarsym(symtableentry).varoptions then
  268. begin
  269. resultdef:=tprocdef(symtableentry.owner.defowner)._class;
  270. resultdef:=tclassrefdef.create(resultdef);
  271. end
  272. else
  273. resultdef:=tabstractvarsym(symtableentry).vardef;
  274. end;
  275. procsym :
  276. begin
  277. { Return the first procdef. In case of overlaoded
  278. procdefs the matching procdef will be choosen
  279. when the expected procvardef is known, see get_information
  280. in htypechk.pas (PFV) }
  281. if not assigned(procdef) then
  282. procdef:=tprocdef(tprocsym(symtableentry).ProcdefList[0])
  283. else if po_kylixlocal in procdef.procoptions then
  284. CGMessage(type_e_cant_take_address_of_local_subroutine);
  285. { the result is a procdef, addrn and proc_to_procvar
  286. typeconvn need this as resultdef so they know
  287. that the address needs to be returned }
  288. resultdef:=procdef;
  289. { process methodpointer }
  290. if assigned(left) then
  291. typecheckpass(left);
  292. end;
  293. labelsym:
  294. resultdef:=voidtype;
  295. else
  296. internalerror(200104141);
  297. end;
  298. end;
  299. procedure Tloadnode.mark_write;
  300. begin
  301. include(flags,nf_write);
  302. end;
  303. function tloadnode.pass_1 : tnode;
  304. begin
  305. result:=nil;
  306. expectloc:=LOC_REFERENCE;
  307. registersint:=0;
  308. registersfpu:=0;
  309. {$ifdef SUPPORT_MMX}
  310. registersmmx:=0;
  311. {$endif SUPPORT_MMX}
  312. if (cs_create_pic in current_settings.moduleswitches) and
  313. not(symtableentry.typ in [paravarsym,localvarsym]) then
  314. include(current_procinfo.flags,pi_needs_got);
  315. case symtableentry.typ of
  316. absolutevarsym :
  317. ;
  318. constsym:
  319. begin
  320. if tconstsym(symtableentry).consttyp=constresourcestring then
  321. expectloc:=LOC_CREFERENCE;
  322. end;
  323. staticvarsym,
  324. localvarsym,
  325. paravarsym :
  326. begin
  327. if assigned(left) then
  328. firstpass(left);
  329. if not is_addr_param_load and
  330. tabstractvarsym(symtableentry).is_regvar(is_addr_param_load) then
  331. expectloc:=tvarregable2tcgloc[tabstractvarsym(symtableentry).varregable]
  332. else
  333. if (tabstractvarsym(symtableentry).varspez=vs_const) then
  334. expectloc:=LOC_CREFERENCE;
  335. { we need a register for call by reference parameters }
  336. if paramanager.push_addr_param(tabstractvarsym(symtableentry).varspez,tabstractvarsym(symtableentry).vardef,pocall_default) then
  337. registersint:=1;
  338. if ([vo_is_thread_var,vo_is_dll_var]*tabstractvarsym(symtableentry).varoptions)<>[] then
  339. registersint:=1;
  340. if (target_info.system=system_powerpc_darwin) and
  341. ([vo_is_dll_var,vo_is_external] * tabstractvarsym(symtableentry).varoptions <> []) then
  342. include(current_procinfo.flags,pi_needs_got);
  343. { call to get address of threadvar }
  344. if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
  345. include(current_procinfo.flags,pi_do_call);
  346. if nf_write in flags then
  347. Tabstractvarsym(symtableentry).trigger_notifications(vn_onwrite)
  348. else
  349. Tabstractvarsym(symtableentry).trigger_notifications(vn_onread);
  350. { count variable references }
  351. if cg.t_times>1 then
  352. tabstractvarsym(symtableentry).IncRefCountBy(cg.t_times-1);
  353. end;
  354. procsym :
  355. begin
  356. { method pointer ? }
  357. if assigned(left) then
  358. begin
  359. expectloc:=LOC_CREFERENCE;
  360. firstpass(left);
  361. registersint:=max(registersint,left.registersint);
  362. registersfpu:=max(registersfpu,left.registersfpu);
  363. {$ifdef SUPPORT_MMX}
  364. registersmmx:=max(registersmmx,left.registersmmx);
  365. {$endif SUPPORT_MMX}
  366. end;
  367. end;
  368. labelsym :
  369. ;
  370. else
  371. internalerror(200104143);
  372. end;
  373. end;
  374. function tloadnode.docompare(p: tnode): boolean;
  375. begin
  376. docompare :=
  377. inherited docompare(p) and
  378. (symtableentry = tloadnode(p).symtableentry) and
  379. (procdef = tloadnode(p).procdef) and
  380. (symtable = tloadnode(p).symtable);
  381. end;
  382. procedure tloadnode.printnodedata(var t:text);
  383. begin
  384. inherited printnodedata(t);
  385. write(t,printnodeindention,'symbol = ',symtableentry.name);
  386. if symtableentry.typ=procsym then
  387. write(t,printnodeindention,'procdef = ',procdef.mangledname);
  388. writeln(t,'');
  389. end;
  390. procedure tloadnode.setprocdef(p : tprocdef);
  391. begin
  392. procdef:=p;
  393. resultdef:=p;
  394. if po_local in p.procoptions then
  395. CGMessage(type_e_cant_take_address_of_local_subroutine);
  396. end;
  397. {*****************************************************************************
  398. TASSIGNMENTNODE
  399. *****************************************************************************}
  400. constructor tassignmentnode.create(l,r : tnode);
  401. begin
  402. inherited create(assignn,l,r);
  403. l.mark_write;
  404. assigntype:=at_normal;
  405. end;
  406. constructor tassignmentnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  407. begin
  408. inherited ppuload(t,ppufile);
  409. assigntype:=tassigntype(ppufile.getbyte);
  410. end;
  411. procedure tassignmentnode.ppuwrite(ppufile:tcompilerppufile);
  412. begin
  413. inherited ppuwrite(ppufile);
  414. ppufile.putbyte(byte(assigntype));
  415. end;
  416. function tassignmentnode.dogetcopy : tnode;
  417. var
  418. n : tassignmentnode;
  419. begin
  420. n:=tassignmentnode(inherited dogetcopy);
  421. n.assigntype:=assigntype;
  422. result:=n;
  423. end;
  424. function tassignmentnode.pass_typecheck:tnode;
  425. var
  426. hp : tnode;
  427. useshelper : boolean;
  428. begin
  429. result:=nil;
  430. resultdef:=voidtype;
  431. { must be made unique }
  432. set_unique(left);
  433. typecheckpass(left);
  434. {$ifdef old_append_str}
  435. if is_ansistring(left.resultdef) then
  436. begin
  437. { fold <ansistring>:=<ansistring>+<char|shortstring|ansistring> }
  438. if (right.nodetype=addn) and
  439. left.isequal(tbinarynode(right).left) and
  440. { don't fold multiple concatenations else we could get trouble
  441. with multiple uses of s
  442. }
  443. (tbinarynode(right).left.nodetype<>addn) and
  444. (tbinarynode(right).right.nodetype<>addn) then
  445. begin
  446. { don't do a typecheckpass(right), since then the addnode }
  447. { may insert typeconversions that make this optimization }
  448. { opportunity quite difficult to detect (JM) }
  449. typecheckpass(tbinarynode(right).left);
  450. typecheckpass(tbinarynode(right).right);
  451. if (tbinarynode(right).right.nodetype=stringconstn) or
  452. is_char(tbinarynode(right).right.resultdef) or
  453. is_shortstring(tbinarynode(right).right.resultdef) or
  454. is_ansistring(tbinarynode(right).right.resultdef) then
  455. begin
  456. { remove property flag so it'll not trigger an error }
  457. exclude(left.flags,nf_isproperty);
  458. { generate call to helper }
  459. hp:=ccallparanode.create(tbinarynode(right).right,
  460. ccallparanode.create(left,nil));
  461. if is_char(tbinarynode(right).right.resultdef) then
  462. result:=ccallnode.createintern('fpc_'+Tstringdef(left.resultdef).stringtypname+'_append_char',hp)
  463. else if is_shortstring(tbinarynode(right).right.resultdef) then
  464. result:=ccallnode.createintern('fpc_'+Tstringdef(left.resultdef).stringtypname+'_append_shortstring',hp)
  465. else
  466. result:=ccallnode.createintern('fpc_'+Tstringdef(left.resultdef).stringtypname+'_append_ansistring',hp);
  467. tbinarynode(right).right:=nil;
  468. left:=nil;
  469. exit;
  470. end;
  471. end;
  472. end
  473. else
  474. if is_shortstring(left.resultdef) then
  475. begin
  476. { fold <shortstring>:=<shortstring>+<shortstring>,
  477. <shortstring>+<char> is handled by an optimized node }
  478. if (right.nodetype=addn) and
  479. left.isequal(tbinarynode(right).left) and
  480. { don't fold multiple concatenations else we could get trouble
  481. with multiple uses of s }
  482. (tbinarynode(right).left.nodetype<>addn) and
  483. (tbinarynode(right).right.nodetype<>addn) then
  484. begin
  485. { don't do a typecheckpass(right), since then the addnode }
  486. { may insert typeconversions that make this optimization }
  487. { opportunity quite difficult to detect (JM) }
  488. typecheckpass(tbinarynode(right).left);
  489. typecheckpass(tbinarynode(right).right);
  490. if is_shortstring(tbinarynode(right).right.resultdef) then
  491. begin
  492. { remove property flag so it'll not trigger an error }
  493. exclude(left.flags,nf_isproperty);
  494. { generate call to helper }
  495. hp:=ccallparanode.create(tbinarynode(right).right,
  496. ccallparanode.create(left,nil));
  497. if is_shortstring(tbinarynode(right).right.resultdef) then
  498. result:=ccallnode.createintern('fpc_shortstr_append_shortstr',hp);
  499. tbinarynode(right).right:=nil;
  500. left:=nil;
  501. exit;
  502. end;
  503. end;
  504. end;
  505. {$endif old_append_str}
  506. typecheckpass(right);
  507. set_varstate(right,vs_read,[vsf_must_be_valid]);
  508. set_varstate(left,vs_written,[]);
  509. if codegenerror then
  510. exit;
  511. { tp procvar support, when we don't expect a procvar
  512. then we need to call the procvar }
  513. if (left.resultdef.typ<>procvardef) then
  514. maybe_call_procvar(right,true);
  515. { assignments to formaldefs and open arrays aren't allowed }
  516. if (left.resultdef.typ=formaldef) or
  517. is_open_array(left.resultdef) then
  518. CGMessage(type_e_assignment_not_allowed);
  519. { test if node can be assigned, properties are allowed }
  520. valid_for_assignment(left,true);
  521. { assigning nil to a dynamic array clears the array }
  522. if is_dynamic_array(left.resultdef) and
  523. (right.nodetype=niln) then
  524. begin
  525. { remove property flag to avoid errors, see comments for }
  526. { tf_winlikewidestring assignments below }
  527. exclude(left.flags,nf_isproperty);
  528. hp:=ccallparanode.create(caddrnode.create_internal
  529. (crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
  530. ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
  531. result := ccallnode.createintern('fpc_dynarray_clear',hp);
  532. left:=nil;
  533. exit;
  534. end;
  535. { shortstring helpers can do the conversion directly,
  536. so treat them separatly }
  537. if (is_shortstring(left.resultdef)) then
  538. begin
  539. { insert typeconv, except for chars that are handled in
  540. secondpass and except for ansi/wide string that can
  541. be converted immediatly }
  542. if not(is_char(right.resultdef) or
  543. (right.resultdef.typ=stringdef)) then
  544. inserttypeconv(right,left.resultdef);
  545. if right.resultdef.typ=stringdef then
  546. begin
  547. useshelper:=true;
  548. { convert constant strings to shortstrings. But
  549. skip empty constant strings, that will be handled
  550. in secondpass }
  551. if (right.nodetype=stringconstn) then
  552. begin
  553. { verify if range fits within shortstring }
  554. { just emit a warning, delphi gives an }
  555. { error, only if the type definition of }
  556. { of the string is less < 255 characters }
  557. if not is_open_string(left.resultdef) and
  558. (tstringconstnode(right).len > tstringdef(left.resultdef).len) then
  559. cgmessage(type_w_string_too_long);
  560. inserttypeconv(right,left.resultdef);
  561. if (tstringconstnode(right).len=0) then
  562. useshelper:=false;
  563. end;
  564. { rest is done in pass 1 (JM) }
  565. if useshelper then
  566. exit;
  567. end
  568. end
  569. else
  570. begin
  571. { check if the assignment may cause a range check error }
  572. check_ranges(fileinfo,right,left.resultdef);
  573. inserttypeconv(right,left.resultdef);
  574. end;
  575. { call helpers for interface }
  576. if is_interfacecom(left.resultdef) then
  577. begin
  578. { remove property flag to avoid errors, see comments for }
  579. { tf_winlikewidestring assignments below }
  580. exclude(left.flags,nf_isproperty);
  581. if right.resultdef.is_related(left.resultdef) then
  582. begin
  583. hp:=
  584. ccallparanode.create(
  585. ctypeconvnode.create_internal(right,voidpointertype),
  586. ccallparanode.create(
  587. ctypeconvnode.create_internal(left,voidpointertype),
  588. nil));
  589. result:=ccallnode.createintern('fpc_intf_assign',hp)
  590. end
  591. else
  592. begin
  593. hp:=
  594. ccallparanode.create(
  595. cguidconstnode.create(tobjectdef(left.resultdef).iidguid^),
  596. ccallparanode.create(
  597. ctypeconvnode.create_internal(right,voidpointertype),
  598. ccallparanode.create(
  599. ctypeconvnode.create_internal(left,voidpointertype),
  600. nil)));
  601. result:=ccallnode.createintern('fpc_intf_assign_by_iid',hp);
  602. end;
  603. left:=nil;
  604. right:=nil;
  605. exit;
  606. end;
  607. { call helpers for variant, they can contain non ref. counted types like
  608. vararrays which must be really copied }
  609. if left.resultdef.typ=variantdef then
  610. begin
  611. hp:=ccallparanode.create(ctypeconvnode.create_internal(
  612. caddrnode.create_internal(right),voidpointertype),
  613. ccallparanode.create(ctypeconvnode.create_internal(
  614. caddrnode.create_internal(left),voidpointertype),
  615. nil));
  616. result:=ccallnode.createintern('fpc_variant_copy',hp);
  617. left:=nil;
  618. right:=nil;
  619. exit;
  620. end;
  621. { call helpers for composite types containing automated types }
  622. if (left.resultdef.needs_inittable) and
  623. (left.resultdef.typ in [arraydef,objectdef,recorddef]) then
  624. begin
  625. hp:=ccallparanode.create(caddrnode.create_internal(
  626. crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
  627. ccallparanode.create(ctypeconvnode.create_internal(
  628. caddrnode.create_internal(left),voidpointertype),
  629. ccallparanode.create(ctypeconvnode.create_internal(
  630. caddrnode.create_internal(right),voidpointertype),
  631. nil)));
  632. result:=ccallnode.createintern('fpc_copy',hp);
  633. left:=nil;
  634. right:=nil;
  635. exit;
  636. end;
  637. { call helpers for windows widestrings, they aren't ref. counted }
  638. if (tf_winlikewidestring in target_info.flags) and is_widestring(left.resultdef) then
  639. begin
  640. { The first argument of fpc_widestr_assign is a var parameter. Properties cannot }
  641. { be passed to var or out parameters, because in that case setters/getters are not }
  642. { used. Further, if we would allow it in case there are no getters or setters, you }
  643. { would need source changes in case these are introduced later on, thus defeating }
  644. { part of the transparency advantages of properties. In this particular case, }
  645. { however: }
  646. { a) if there is a setter, this code will not be used since then the assignment }
  647. { will be converted to a procedure call }
  648. { b) the getter is irrelevant, because fpc_widestr_assign must always decrease }
  649. { the refcount of the field to which we are writing }
  650. { c) source code changes are not required if a setter is added/removed, because }
  651. { this transformation is handled at compile time }
  652. { -> we can remove the nf_isproperty flag (if any) from left, so that in case it }
  653. { is a property which refers to a field without a setter call, we will not get }
  654. { an error about trying to pass a property as a var parameter }
  655. exclude(left.flags,nf_isproperty);
  656. hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
  657. ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
  658. nil));
  659. result:=ccallnode.createintern('fpc_widestr_assign',hp);
  660. left:=nil;
  661. right:=nil;
  662. exit;
  663. end;
  664. { check if local proc/func is assigned to procvar }
  665. if right.resultdef.typ=procvardef then
  666. test_local_to_procvar(tprocvardef(right.resultdef),left.resultdef);
  667. end;
  668. function tassignmentnode.pass_1 : tnode;
  669. var
  670. hp: tnode;
  671. oldassignmentnode : tassignmentnode;
  672. begin
  673. result:=nil;
  674. expectloc:=LOC_VOID;
  675. firstpass(left);
  676. { Optimize the reuse of the destination of the assingment in left.
  677. Allow the use of the left inside the tree generated on the right.
  678. This is especially usefull for string routines where the destination
  679. is pushed as a parameter. Using the final destination of left directly
  680. save a temp allocation and copy of data (PFV) }
  681. oldassignmentnode:=aktassignmentnode;
  682. if right.nodetype=addn then
  683. aktassignmentnode:=self
  684. else
  685. aktassignmentnode:=nil;
  686. firstpass(right);
  687. aktassignmentnode:=oldassignmentnode;
  688. if nf_assign_done_in_right in flags then
  689. begin
  690. result:=right;
  691. right:=nil;
  692. exit;
  693. end;
  694. if codegenerror then
  695. exit;
  696. { if right is a function call for which the address of the result }
  697. { is allocated by the caller and passed to the function via an }
  698. { invisible function result, try to pass the x in "x:=f(...)" as }
  699. { that function result instead. Condition: x cannot be accessible }
  700. { from within f. This is the case if x is a temp, or x is a local }
  701. { variable or value parameter of the current block and its address }
  702. { is not passed to f. One problem: what if someone takes the }
  703. { address of x, puts it in a pointer variable/field and then }
  704. { accesses it that way from within the function? This is solved }
  705. { (in a conservative way) using the ti_addr_taken/addr_taken flags }
  706. if (cs_opt_level1 in current_settings.optimizerswitches) and
  707. (right.nodetype = calln) and
  708. (right.resultdef=left.resultdef) and
  709. { left must be a temp, since otherwise as soon as you modify the }
  710. { result, the current left node is modified and that one may }
  711. { still be an argument to the function or even accessed in the }
  712. { function }
  713. (
  714. (
  715. (((left.nodetype = temprefn) and
  716. not(ti_addr_taken in ttemprefnode(left).tempinfo^.flags) and
  717. not(ti_may_be_in_reg in ttemprefnode(left).tempinfo^.flags)) or
  718. ((left.nodetype = loadn) and
  719. { nested procedures may access the current procedure's locals }
  720. (tcallnode(right).procdefinition.parast.symtablelevel=normal_function_level) and
  721. { must be a local variable or a value para }
  722. ((tloadnode(left).symtableentry.typ = localvarsym) or
  723. ((tloadnode(left).symtableentry.typ = paravarsym) and
  724. (tparavarsym(tloadnode(left).symtableentry).varspez = vs_value)
  725. )
  726. ) and
  727. { the address may not have been taken of the variable/parameter, because }
  728. { otherwise it's possible that the called function can access it via a }
  729. { global variable or other stored state }
  730. not(tabstractvarsym(tloadnode(left).symtableentry).addr_taken) and
  731. (tabstractvarsym(tloadnode(left).symtableentry).varregable in [vr_none,vr_addr])
  732. )
  733. ) and
  734. paramanager.ret_in_param(right.resultdef,tcallnode(right).procdefinition.proccalloption)
  735. ) or
  736. { there's special support for ansi/widestrings in the callnode }
  737. is_ansistring(right.resultdef) or
  738. is_widestring(right.resultdef)
  739. ) then
  740. begin
  741. if assigned(tcallnode(right).funcretnode) then
  742. internalerror(2007080201);
  743. tcallnode(right).funcretnode := left;
  744. result := right;
  745. left := nil;
  746. right := nil;
  747. exit;
  748. end;
  749. { assignment to refcounted variable -> inc/decref }
  750. if (not is_class(left.resultdef) and
  751. left.resultdef.needs_inittable) then
  752. include(current_procinfo.flags,pi_do_call);
  753. if (is_shortstring(left.resultdef)) then
  754. begin
  755. if right.resultdef.typ=stringdef then
  756. begin
  757. if (right.nodetype<>stringconstn) or
  758. (tstringconstnode(right).len<>0) then
  759. begin
  760. {$ifdef old_append_str}
  761. if (cs_opt_level1 in current_settings.optimizerswitches) and
  762. (right.nodetype in [calln,blockn]) and
  763. (left.nodetype = temprefn) and
  764. is_shortstring(right.resultdef) and
  765. not is_open_string(left.resultdef) and
  766. (tstringdef(left.resultdef).len = 255) then
  767. begin
  768. { the blocknode case is handled in pass_generate_code at the temp }
  769. { reference level (mainly for callparatemp) (JM) }
  770. if (right.nodetype = calln) then
  771. begin
  772. tcallnode(right).funcretnode := left;
  773. result := right;
  774. end
  775. else
  776. exit;
  777. end
  778. else
  779. {$endif old_append_str}
  780. begin
  781. hp:=ccallparanode.create
  782. (right,
  783. ccallparanode.create(cinlinenode.create
  784. (in_high_x,false,left.getcopy),nil));
  785. result:=ccallnode.createinternreturn('fpc_'+tstringdef(right.resultdef).stringtypname+'_to_shortstr',hp,left);
  786. firstpass(result);
  787. end;
  788. left:=nil;
  789. right:=nil;
  790. exit;
  791. end;
  792. end;
  793. end;
  794. registersint:=left.registersint+right.registersint;
  795. registersfpu:=max(left.registersfpu,right.registersfpu);
  796. {$ifdef SUPPORT_MMX}
  797. registersmmx:=max(left.registersmmx,right.registersmmx);
  798. {$endif SUPPORT_MMX}
  799. end;
  800. function tassignmentnode.docompare(p: tnode): boolean;
  801. begin
  802. docompare :=
  803. inherited docompare(p) and
  804. (assigntype = tassignmentnode(p).assigntype);
  805. end;
  806. {$ifdef state_tracking}
  807. function Tassignmentnode.track_state_pass(exec_known:boolean):boolean;
  808. var se:Tstate_entry;
  809. begin
  810. track_state_pass:=false;
  811. if exec_known then
  812. begin
  813. track_state_pass:=right.track_state_pass(exec_known);
  814. {Force a new resultdef pass.}
  815. right.resultdef:=nil;
  816. do_typecheckpass(right);
  817. typecheckpass(right);
  818. aktstate.store_fact(left.getcopy,right.getcopy);
  819. end
  820. else
  821. aktstate.delete_fact(left);
  822. end;
  823. {$endif}
  824. {*****************************************************************************
  825. TARRAYCONSTRUCTORRANGENODE
  826. *****************************************************************************}
  827. constructor tarrayconstructorrangenode.create(l,r : tnode);
  828. begin
  829. inherited create(arrayconstructorrangen,l,r);
  830. end;
  831. function tarrayconstructorrangenode.pass_typecheck:tnode;
  832. begin
  833. result:=nil;
  834. typecheckpass(left);
  835. typecheckpass(right);
  836. set_varstate(left,vs_read,[vsf_must_be_valid]);
  837. set_varstate(right,vs_read,[vsf_must_be_valid]);
  838. if codegenerror then
  839. exit;
  840. resultdef:=left.resultdef;
  841. end;
  842. function tarrayconstructorrangenode.pass_1 : tnode;
  843. begin
  844. firstpass(left);
  845. firstpass(right);
  846. expectloc:=LOC_CREFERENCE;
  847. calcregisters(self,0,0,0);
  848. result:=nil;
  849. end;
  850. {****************************************************************************
  851. TARRAYCONSTRUCTORNODE
  852. *****************************************************************************}
  853. constructor tarrayconstructornode.create(l,r : tnode);
  854. begin
  855. inherited create(arrayconstructorn,l,r);
  856. end;
  857. function tarrayconstructornode.dogetcopy : tnode;
  858. var
  859. n : tarrayconstructornode;
  860. begin
  861. n:=tarrayconstructornode(inherited dogetcopy);
  862. result:=n;
  863. end;
  864. function tarrayconstructornode.pass_typecheck:tnode;
  865. var
  866. hdef : tdef;
  867. hp : tarrayconstructornode;
  868. len : longint;
  869. varia : boolean;
  870. eq : tequaltype;
  871. hnodetype : tnodetype;
  872. begin
  873. result:=nil;
  874. { are we allowing array constructor? Then convert it to a set.
  875. Do this only if we didn't convert the arrayconstructor yet. This
  876. is needed for the cases where the resultdef is forced for a second
  877. run }
  878. if (not allow_array_constructor) then
  879. begin
  880. hp:=tarrayconstructornode(getcopy);
  881. arrayconstructor_to_set(tnode(hp));
  882. result:=hp;
  883. exit;
  884. end;
  885. { only pass left tree, right tree contains next construct if any }
  886. hdef:=nil;
  887. hnodetype:=errorn;
  888. len:=0;
  889. varia:=false;
  890. if assigned(left) then
  891. begin
  892. hp:=self;
  893. while assigned(hp) do
  894. begin
  895. typecheckpass(hp.left);
  896. set_varstate(hp.left,vs_read,[vsf_must_be_valid]);
  897. if (hdef=nil) then
  898. begin
  899. hdef:=hp.left.resultdef;
  900. hnodetype:=hp.left.nodetype;
  901. end
  902. else
  903. begin
  904. { If we got a niln we don't know the type yet and need to take the
  905. type of the next array element.
  906. This is to handle things like [nil,tclass,tclass], see also tw8371 (PFV) }
  907. if hnodetype=niln then
  908. begin
  909. eq:=compare_defs(hp.left.resultdef,hdef,hnodetype);
  910. if eq>te_incompatible then
  911. begin
  912. hdef:=hp.left.resultdef;
  913. hnodetype:=hp.left.nodetype;
  914. end;
  915. end
  916. else
  917. eq:=compare_defs(hdef,hp.left.resultdef,hp.left.nodetype);
  918. if (not varia) and (eq<te_equal) then
  919. begin
  920. { If both are integers we need to take the type that can hold both
  921. defs }
  922. if is_integer(hdef) and is_integer(hp.left.resultdef) then
  923. begin
  924. if is_in_limit(hdef,hp.left.resultdef) then
  925. hdef:=hp.left.resultdef;
  926. end
  927. else
  928. if (nf_novariaallowed in flags) then
  929. varia:=true;
  930. end;
  931. end;
  932. inc(len);
  933. hp:=tarrayconstructornode(hp.right);
  934. end;
  935. end;
  936. { Set the type of empty or varia arrays to void. Also
  937. do this if the type is array of const/open array
  938. because those can't be used with setelementdef }
  939. if not assigned(hdef) or
  940. varia or
  941. is_array_of_const(hdef) or
  942. is_open_array(hdef) then
  943. hdef:=voidtype;
  944. resultdef:=tarraydef.create(0,len-1,s32inttype);
  945. tarraydef(resultdef).elementdef:=hdef;
  946. include(tarraydef(resultdef).arrayoptions,ado_IsConstructor);
  947. if varia then
  948. include(tarraydef(resultdef).arrayoptions,ado_IsVariant);
  949. end;
  950. procedure tarrayconstructornode.force_type(def:tdef);
  951. var
  952. hp : tarrayconstructornode;
  953. begin
  954. tarraydef(resultdef).elementdef:=def;
  955. include(tarraydef(resultdef).arrayoptions,ado_IsConstructor);
  956. exclude(tarraydef(resultdef).arrayoptions,ado_IsVariant);
  957. if assigned(left) then
  958. begin
  959. hp:=self;
  960. while assigned(hp) do
  961. begin
  962. inserttypeconv(hp.left,def);
  963. hp:=tarrayconstructornode(hp.right);
  964. end;
  965. end;
  966. end;
  967. procedure tarrayconstructornode.insert_typeconvs;
  968. var
  969. hp : tarrayconstructornode;
  970. dovariant : boolean;
  971. begin
  972. dovariant:=(nf_forcevaria in flags) or (ado_isvariant in tarraydef(resultdef).arrayoptions);
  973. { only pass left tree, right tree contains next construct if any }
  974. if assigned(left) then
  975. begin
  976. hp:=self;
  977. while assigned(hp) do
  978. begin
  979. typecheckpass(hp.left);
  980. { Insert typeconvs for array of const }
  981. if dovariant then
  982. { at this time C varargs are no longer an arrayconstructornode }
  983. insert_varargstypeconv(hp.left,false);
  984. hp:=tarrayconstructornode(hp.right);
  985. end;
  986. end;
  987. end;
  988. function tarrayconstructornode.pass_1 : tnode;
  989. var
  990. hp : tarrayconstructornode;
  991. do_variant:boolean;
  992. begin
  993. do_variant:=(nf_forcevaria in flags) or (ado_isvariant in tarraydef(resultdef).arrayoptions);
  994. result:=nil;
  995. { Insert required type convs, this must be
  996. done in pass 1, because the call must be
  997. typecheckpassed already }
  998. if assigned(left) then
  999. begin
  1000. insert_typeconvs;
  1001. { call firstpass for all nodes }
  1002. hp:=self;
  1003. while assigned(hp) do
  1004. begin
  1005. if hp.left<>nil then
  1006. begin
  1007. {This check is pessimistic; a call will happen depending
  1008. on the location in which the elements will be found in
  1009. pass 2.}
  1010. if not do_variant then
  1011. include(current_procinfo.flags,pi_do_call);
  1012. firstpass(hp.left);
  1013. end;
  1014. hp:=tarrayconstructornode(hp.right);
  1015. end;
  1016. end;
  1017. expectloc:=LOC_CREFERENCE;
  1018. calcregisters(self,0,0,0);
  1019. end;
  1020. function tarrayconstructornode.docompare(p: tnode): boolean;
  1021. begin
  1022. docompare:=inherited docompare(p);
  1023. end;
  1024. {*****************************************************************************
  1025. TTYPENODE
  1026. *****************************************************************************}
  1027. constructor ttypenode.create(def:tdef);
  1028. begin
  1029. inherited create(typen);
  1030. typedef:=def;
  1031. allowed:=false;
  1032. end;
  1033. constructor ttypenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1034. begin
  1035. inherited ppuload(t,ppufile);
  1036. ppufile.getderef(typedefderef);
  1037. allowed:=boolean(ppufile.getbyte);
  1038. end;
  1039. procedure ttypenode.ppuwrite(ppufile:tcompilerppufile);
  1040. begin
  1041. inherited ppuwrite(ppufile);
  1042. ppufile.putderef(typedefderef);
  1043. ppufile.putbyte(byte(allowed));
  1044. end;
  1045. procedure ttypenode.buildderefimpl;
  1046. begin
  1047. inherited buildderefimpl;
  1048. typedefderef.build(typedef);
  1049. end;
  1050. procedure ttypenode.derefimpl;
  1051. begin
  1052. inherited derefimpl;
  1053. typedef:=tdef(typedefderef.resolve);
  1054. end;
  1055. function ttypenode.pass_typecheck:tnode;
  1056. begin
  1057. result:=nil;
  1058. resultdef:=typedef;
  1059. { check if it's valid }
  1060. if typedef.typ = errordef then
  1061. CGMessage(parser_e_illegal_expression);
  1062. end;
  1063. function ttypenode.pass_1 : tnode;
  1064. begin
  1065. result:=nil;
  1066. expectloc:=LOC_VOID;
  1067. { a typenode can't generate code, so we give here
  1068. an error. Else it'll be an abstract error in pass_generate_code.
  1069. Only when the allowed flag is set we don't generate
  1070. an error }
  1071. if not allowed then
  1072. Message(parser_e_no_type_not_allowed_here);
  1073. end;
  1074. function ttypenode.dogetcopy : tnode;
  1075. var
  1076. n : ttypenode;
  1077. begin
  1078. n:=ttypenode(inherited dogetcopy);
  1079. n.allowed:=allowed;
  1080. n.typedef:=typedef;
  1081. result:=n;
  1082. end;
  1083. function ttypenode.docompare(p: tnode): boolean;
  1084. begin
  1085. docompare :=
  1086. inherited docompare(p);
  1087. end;
  1088. {*****************************************************************************
  1089. TRTTINODE
  1090. *****************************************************************************}
  1091. constructor trttinode.create(def:tstoreddef;rt:trttitype;dt:Trttidatatype);
  1092. begin
  1093. inherited create(rttin);
  1094. rttidef:=def;
  1095. rttitype:=rt;
  1096. rttidatatype:=dt;
  1097. end;
  1098. constructor trttinode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1099. begin
  1100. inherited ppuload(t,ppufile);
  1101. ppufile.getderef(rttidefderef);
  1102. rttitype:=trttitype(ppufile.getbyte);
  1103. end;
  1104. procedure trttinode.ppuwrite(ppufile:tcompilerppufile);
  1105. begin
  1106. inherited ppuwrite(ppufile);
  1107. ppufile.putderef(rttidefderef);
  1108. ppufile.putbyte(byte(rttitype));
  1109. end;
  1110. procedure trttinode.buildderefimpl;
  1111. begin
  1112. inherited buildderefimpl;
  1113. rttidefderef.build(rttidef);
  1114. end;
  1115. procedure trttinode.derefimpl;
  1116. begin
  1117. inherited derefimpl;
  1118. rttidef:=tstoreddef(rttidefderef.resolve);
  1119. end;
  1120. function trttinode.dogetcopy : tnode;
  1121. var
  1122. n : trttinode;
  1123. begin
  1124. n:=trttinode(inherited dogetcopy);
  1125. n.rttidef:=rttidef;
  1126. n.rttitype:=rttitype;
  1127. result:=n;
  1128. end;
  1129. function trttinode.pass_typecheck:tnode;
  1130. begin
  1131. { rtti information will be returned as a void pointer }
  1132. result:=nil;
  1133. resultdef:=voidpointertype;
  1134. end;
  1135. function trttinode.pass_1 : tnode;
  1136. begin
  1137. result:=nil;
  1138. expectloc:=LOC_CREFERENCE;
  1139. end;
  1140. function trttinode.docompare(p: tnode): boolean;
  1141. begin
  1142. docompare :=
  1143. inherited docompare(p) and
  1144. (rttidef = trttinode(p).rttidef) and
  1145. (rttitype = trttinode(p).rttitype);
  1146. end;
  1147. begin
  1148. cloadnode:=tloadnode;
  1149. cassignmentnode:=tassignmentnode;
  1150. carrayconstructorrangenode:=tarrayconstructorrangenode;
  1151. carrayconstructornode:=tarrayconstructornode;
  1152. ctypenode:=ttypenode;
  1153. crttinode:=trttinode;
  1154. end.