pstatmnt.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Does the parsing of the statements
  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 pstatmnt;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. tokens,node;
  22. function statement_block(starttoken : ttoken) : tnode;
  23. { reads an assembler block }
  24. function assembler_block : tnode;
  25. implementation
  26. uses
  27. { common }
  28. cutils,cclasses,
  29. { global }
  30. globtype,globals,verbose,constexp,
  31. systems,
  32. { aasm }
  33. cpubase,aasmtai,aasmdata,
  34. { symtable }
  35. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  36. paramgr,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nutils,ngenutil,nbas,ncal,nmem,nset,ncnv,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,ptype,pexpr,
  43. { codegen }
  44. procinfo,cgbase,
  45. { assembler reader }
  46. rabase;
  47. function statement : tnode;forward;
  48. function if_statement : tnode;
  49. var
  50. ex,if_a,else_a : tnode;
  51. begin
  52. consume(_IF);
  53. ex:=comp_expr([ef_accept_equal]);
  54. consume(_THEN);
  55. if not(token in endtokens) then
  56. if_a:=statement
  57. else
  58. if_a:=nil;
  59. if try_to_consume(_ELSE) then
  60. else_a:=statement
  61. else
  62. else_a:=nil;
  63. result:=cifnode.create(ex,if_a,else_a);
  64. end;
  65. { creates a block (list) of statements, til the next END token }
  66. function statements_til_end : tnode;
  67. var
  68. first,last : tstatementnode;
  69. begin
  70. first:=nil;
  71. last:=nil;
  72. while token<>_END do
  73. begin
  74. if first=nil then
  75. begin
  76. last:=cstatementnode.create(statement,nil);
  77. first:=last;
  78. end
  79. else
  80. begin
  81. last.right:=cstatementnode.create(statement,nil);
  82. last:=tstatementnode(last.right);
  83. end;
  84. if not try_to_consume(_SEMICOLON) then
  85. break;
  86. consume_emptystats;
  87. end;
  88. consume(_END);
  89. statements_til_end:=cblocknode.create(first);
  90. end;
  91. function case_statement : tnode;
  92. var
  93. casedef : tdef;
  94. caseexpr,p : tnode;
  95. blockid : longint;
  96. hl1,hl2 : TConstExprInt;
  97. sl1,sl2 : tstringconstnode;
  98. casedeferror, caseofstring : boolean;
  99. casenode : tcasenode;
  100. begin
  101. consume(_CASE);
  102. caseexpr:=comp_expr([ef_accept_equal]);
  103. { determines result type }
  104. do_typecheckpass(caseexpr);
  105. { variants must be accepted, but first they must be converted to integer }
  106. if caseexpr.resultdef.typ=variantdef then
  107. begin
  108. caseexpr:=ctypeconvnode.create_internal(caseexpr,sinttype);
  109. do_typecheckpass(caseexpr);
  110. end;
  111. set_varstate(caseexpr,vs_read,[vsf_must_be_valid]);
  112. casedeferror:=false;
  113. casedef:=caseexpr.resultdef;
  114. { case of string must be rejected in delphi-, }
  115. { tp7/bp7-, mac-compatibility modes. }
  116. caseofstring :=
  117. ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and
  118. is_string(casedef);
  119. if (not assigned(casedef)) or
  120. ( not(is_ordinal(casedef)) and (not caseofstring) ) then
  121. begin
  122. CGMessage(type_e_ordinal_or_string_expr_expected);
  123. { create a correct tree }
  124. caseexpr.free;
  125. caseexpr:=cordconstnode.create(0,u32inttype,false);
  126. { set error flag so no rangechecks are done }
  127. casedeferror:=true;
  128. end;
  129. { Create casenode }
  130. casenode:=ccasenode.create(caseexpr);
  131. consume(_OF);
  132. { Parse all case blocks }
  133. blockid:=0;
  134. repeat
  135. { maybe an instruction has more case labels }
  136. repeat
  137. p:=expr(true);
  138. if is_widechar(casedef) then
  139. begin
  140. if (p.nodetype=rangen) then
  141. begin
  142. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  143. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  144. do_typecheckpass(trangenode(p).left);
  145. do_typecheckpass(trangenode(p).right);
  146. end
  147. else
  148. begin
  149. p:=ctypeconvnode.create(p,cwidechartype);
  150. do_typecheckpass(p);
  151. end;
  152. end
  153. else
  154. begin
  155. if is_char(casedef) and is_widechar(p.resultdef) then
  156. begin
  157. if (p.nodetype=ordconstn) then
  158. begin
  159. p:=ctypeconvnode.create(p,cansichartype);
  160. do_typecheckpass(p);
  161. end
  162. else if (p.nodetype=rangen) then
  163. begin
  164. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cansichartype);
  165. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cansichartype);
  166. do_typecheckpass(trangenode(p).left);
  167. do_typecheckpass(trangenode(p).right);
  168. end;
  169. end;
  170. end;
  171. hl1:=0;
  172. hl2:=0;
  173. sl1:=nil;
  174. sl2:=nil;
  175. if (p.nodetype=rangen) then
  176. begin
  177. { type check for string case statements }
  178. if caseofstring and
  179. is_conststring_or_constcharnode(trangenode(p).left) and
  180. is_conststring_or_constcharnode(trangenode(p).right) then
  181. begin
  182. { we need stringconstnodes, even if expression contains single chars }
  183. sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
  184. sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
  185. if sl1.fullcompare(sl2) > 0 then
  186. CGMessage(parser_e_case_lower_less_than_upper_bound);
  187. end
  188. { type checking for ordinal case statements }
  189. else if (not caseofstring) and
  190. is_subequal(casedef, trangenode(p).left.resultdef) and
  191. is_subequal(casedef, trangenode(p).right.resultdef) then
  192. begin
  193. hl1:=get_ordinal_value(trangenode(p).left);
  194. hl2:=get_ordinal_value(trangenode(p).right);
  195. if hl1>hl2 then
  196. CGMessage(parser_e_case_lower_less_than_upper_bound);
  197. if not casedeferror then
  198. begin
  199. testrange(casedef,hl1,false,false);
  200. testrange(casedef,hl2,false,false);
  201. end;
  202. end
  203. else
  204. CGMessage(parser_e_case_mismatch);
  205. if caseofstring then
  206. casenode.addlabel(blockid,sl1,sl2)
  207. else
  208. casenode.addlabel(blockid,hl1,hl2);
  209. end
  210. else
  211. begin
  212. { type check for string case statements }
  213. if (caseofstring and (not is_conststring_or_constcharnode(p))) or
  214. { type checking for ordinal case statements }
  215. ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
  216. CGMessage(parser_e_case_mismatch);
  217. if caseofstring then
  218. begin
  219. sl1:=get_string_value(p, tstringdef(casedef));
  220. casenode.addlabel(blockid,sl1,sl1);
  221. end
  222. else
  223. begin
  224. hl1:=get_ordinal_value(p);
  225. if not casedeferror then
  226. testrange(casedef,hl1,false,false);
  227. casenode.addlabel(blockid,hl1,hl1);
  228. end;
  229. end;
  230. p.free;
  231. sl1.free;
  232. sl2.free;
  233. if token=_COMMA then
  234. consume(_COMMA)
  235. else
  236. break;
  237. until false;
  238. consume(_COLON);
  239. { add instruction block }
  240. casenode.addblock(blockid,statement);
  241. { next block }
  242. inc(blockid);
  243. if not(token in [_ELSE,_OTHERWISE,_END]) then
  244. consume(_SEMICOLON);
  245. until (token in [_ELSE,_OTHERWISE,_END]);
  246. if (token in [_ELSE,_OTHERWISE]) then
  247. begin
  248. if not try_to_consume(_ELSE) then
  249. consume(_OTHERWISE);
  250. casenode.addelseblock(statements_til_end);
  251. end
  252. else
  253. consume(_END);
  254. result:=casenode;
  255. end;
  256. function repeat_statement : tnode;
  257. var
  258. first,last,p_e : tnode;
  259. begin
  260. consume(_REPEAT);
  261. first:=nil;
  262. last:=nil;
  263. while token<>_UNTIL do
  264. begin
  265. if first=nil then
  266. begin
  267. last:=cstatementnode.create(statement,nil);
  268. first:=last;
  269. end
  270. else
  271. begin
  272. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  273. last:=tstatementnode(last).right;
  274. end;
  275. if not try_to_consume(_SEMICOLON) then
  276. break;
  277. consume_emptystats;
  278. end;
  279. consume(_UNTIL);
  280. first:=cblocknode.create(first);
  281. p_e:=comp_expr([ef_accept_equal]);
  282. result:=cwhilerepeatnode.create(p_e,first,false,true);
  283. end;
  284. function while_statement : tnode;
  285. var
  286. p_e,p_a : tnode;
  287. begin
  288. consume(_WHILE);
  289. p_e:=comp_expr([ef_accept_equal]);
  290. consume(_DO);
  291. p_a:=statement;
  292. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  293. end;
  294. { a helper function which is used both by "with" and "for-in loop" nodes }
  295. function skip_nodes_before_load(p: tnode): tnode;
  296. begin
  297. { ignore nodes that don't add instructions in the tree }
  298. while assigned(p) and
  299. { equal type conversions }
  300. (
  301. (p.nodetype=typeconvn) and
  302. (ttypeconvnode(p).convtype=tc_equal)
  303. ) or
  304. { constant array index }
  305. (
  306. (p.nodetype=vecn) and
  307. (tvecnode(p).right.nodetype=ordconstn)
  308. ) do
  309. p:=tunarynode(p).left;
  310. result:=p;
  311. end;
  312. function for_statement : tnode;
  313. procedure check_range(hp:tnode; fordef: tdef);
  314. begin
  315. if (hp.nodetype=ordconstn) and
  316. (fordef.typ<>errordef) then
  317. testrange(fordef,tordconstnode(hp).value,false,true);
  318. end;
  319. function for_loop_create(hloopvar: tnode): tnode;
  320. var
  321. hp,
  322. hblock,
  323. hto,hfrom : tnode;
  324. backward : boolean;
  325. loopvarsym : tabstractvarsym;
  326. begin
  327. { Check loop variable }
  328. loopvarsym:=nil;
  329. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  330. if not(is_ordinal(hloopvar.resultdef))
  331. {$ifndef cpu64bitaddr}
  332. or is_64bitint(hloopvar.resultdef)
  333. {$endif not cpu64bitaddr}
  334. then
  335. MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
  336. hp:=hloopvar;
  337. while assigned(hp) and
  338. (
  339. { record/object fields and array elements are allowed }
  340. { in tp7 mode only }
  341. (
  342. (m_tp7 in current_settings.modeswitches) and
  343. (
  344. ((hp.nodetype=subscriptn) and
  345. ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
  346. is_object(tsubscriptnode(hp).left.resultdef))
  347. ) or
  348. { constant array index }
  349. (
  350. (hp.nodetype=vecn) and
  351. is_constintnode(tvecnode(hp).right)
  352. )
  353. )
  354. ) or
  355. { equal typeconversions }
  356. (
  357. (hp.nodetype=typeconvn) and
  358. (ttypeconvnode(hp).convtype=tc_equal)
  359. )
  360. ) do
  361. begin
  362. { Use the recordfield for loopvarsym }
  363. if not assigned(loopvarsym) and
  364. (hp.nodetype=subscriptn) then
  365. loopvarsym:=tsubscriptnode(hp).vs;
  366. hp:=tunarynode(hp).left;
  367. end;
  368. if assigned(hp) and
  369. (hp.nodetype=loadn) then
  370. begin
  371. case tloadnode(hp).symtableentry.typ of
  372. staticvarsym,
  373. localvarsym,
  374. paravarsym :
  375. begin
  376. { we need a simple loadn:
  377. 1. The load must be in a global symtable or
  378. in the same level as the para of the current proc.
  379. 2. value variables (no const,out or var)
  380. 3. No threadvar, readonly or typedconst
  381. }
  382. if (
  383. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  384. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  385. ) and
  386. (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
  387. ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
  388. begin
  389. { Assigning for-loop variable is only allowed in tp7 and macpas }
  390. if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
  391. begin
  392. if not assigned(loopvarsym) then
  393. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  394. include(loopvarsym.varoptions,vo_is_loop_counter);
  395. end;
  396. end
  397. else
  398. begin
  399. { Typed const is allowed in tp7 }
  400. if not(m_tp7 in current_settings.modeswitches) or
  401. not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
  402. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  403. end;
  404. end;
  405. else
  406. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  407. end;
  408. end
  409. else
  410. MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
  411. hfrom:=comp_expr([ef_accept_equal]);
  412. if try_to_consume(_DOWNTO) then
  413. backward:=true
  414. else
  415. begin
  416. consume(_TO);
  417. backward:=false;
  418. end;
  419. hto:=comp_expr([ef_accept_equal]);
  420. consume(_DO);
  421. { Check if the constants fit in the range }
  422. check_range(hfrom,hloopvar.resultdef);
  423. check_range(hto,hloopvar.resultdef);
  424. { first set the varstate for from and to, so
  425. uses of loopvar in those expressions will also
  426. trigger a warning when it is not used yet. This
  427. needs to be done before the instruction block is
  428. parsed to have a valid hloopvar }
  429. typecheckpass(hfrom);
  430. set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
  431. typecheckpass(hto);
  432. set_varstate(hto,vs_read,[vsf_must_be_valid]);
  433. typecheckpass(hloopvar);
  434. { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
  435. { for some subnodes }
  436. set_varstate(hloopvar,vs_written,[]);
  437. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  438. { ... now the instruction block }
  439. hblock:=statement;
  440. { variable is not used for loop counter anymore }
  441. if assigned(loopvarsym) then
  442. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  443. result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
  444. end;
  445. function for_in_loop_create(hloopvar: tnode): tnode;
  446. var
  447. expr,hloopbody,hp: tnode;
  448. loopvarsym: tabstractvarsym;
  449. begin
  450. hp:=skip_nodes_before_load(hloopvar);
  451. if assigned(hp)and(hp.nodetype=loadn) then
  452. begin
  453. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  454. include(loopvarsym.varoptions,vo_is_loop_counter);
  455. end
  456. else
  457. loopvarsym:=nil;
  458. expr:=comp_expr([ef_accept_equal]);
  459. consume(_DO);
  460. set_varstate(hloopvar,vs_written,[]);
  461. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  462. hloopbody:=statement;
  463. if assigned(loopvarsym) then
  464. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  465. result:=create_for_in_loop(hloopvar,hloopbody,expr);
  466. expr.free;
  467. end;
  468. var
  469. hloopvar: tnode;
  470. begin
  471. { parse loop header }
  472. consume(_FOR);
  473. hloopvar:=factor(false,[]);
  474. valid_for_loopvar(hloopvar,true);
  475. if try_to_consume(_ASSIGNMENT) then
  476. result:=for_loop_create(hloopvar)
  477. else if try_to_consume(_IN) then
  478. result:=for_in_loop_create(hloopvar)
  479. else
  480. begin
  481. consume(_ASSIGNMENT); // fail
  482. result:=cerrornode.create;
  483. end;
  484. end;
  485. function _with_statement : tnode;
  486. var
  487. p : tnode;
  488. i : longint;
  489. st : TSymtable;
  490. newblock : tblocknode;
  491. newstatement : tstatementnode;
  492. calltempnode,
  493. tempnode : ttempcreatenode;
  494. valuenode,
  495. hp,
  496. refnode : tnode;
  497. hdef : tdef;
  498. helperdef : tobjectdef;
  499. hasimplicitderef : boolean;
  500. withsymtablelist : TFPObjectList;
  501. procedure pushobjchild(withdef,obj:tobjectdef);
  502. var
  503. parenthelperdef : tobjectdef;
  504. begin
  505. if not assigned(obj) then
  506. exit;
  507. pushobjchild(withdef,obj.childof);
  508. { we need to look for helpers that were defined for the parent
  509. class as well }
  510. search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
  511. { push the symtables of the helper's parents in reverse order }
  512. if assigned(parenthelperdef) then
  513. pushobjchild(withdef,parenthelperdef.childof);
  514. { keep the original tobjectdef as owner, because that is used for
  515. visibility of the symtable }
  516. st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
  517. symtablestack.push(st);
  518. withsymtablelist.add(st);
  519. { push the symtable of the helper }
  520. if assigned(parenthelperdef) then
  521. begin
  522. st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
  523. symtablestack.push(st);
  524. withsymtablelist.add(st);
  525. end;
  526. end;
  527. begin
  528. calltempnode:=nil;
  529. p:=comp_expr([ef_accept_equal]);
  530. do_typecheckpass(p);
  531. if (p.nodetype=vecn) and
  532. (nf_memseg in p.flags) then
  533. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  534. { "with procvar" can never mean anything, so always try
  535. to call it in case it returns a record/object/... }
  536. maybe_call_procvar(p,false);
  537. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) or
  538. ((p.resultdef.typ=undefineddef) and (df_generic in current_procinfo.procdef.defoptions)) then
  539. begin
  540. newblock:=nil;
  541. valuenode:=nil;
  542. tempnode:=nil;
  543. hp:=skip_nodes_before_load(p);
  544. if (hp.nodetype=loadn) and
  545. (
  546. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  547. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  548. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  549. ) and
  550. { MacPas objects are mapped to classes, and the MacPas compilers
  551. interpret with-statements with MacPas objects the same way
  552. as records (the object referenced by the with-statement
  553. must remain constant)
  554. }
  555. not(is_class(hp.resultdef) and
  556. (m_mac in current_settings.modeswitches)) then
  557. begin
  558. { simple load, we can reference direct }
  559. refnode:=p;
  560. end
  561. else
  562. begin
  563. { complex load, load in temp first }
  564. newblock:=internalstatements(newstatement);
  565. { when we can't take the address of p, load it in a temp }
  566. { since we may need its address later on }
  567. if not valid_for_addr(p,false) then
  568. begin
  569. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  570. addstatement(newstatement,calltempnode);
  571. addstatement(newstatement,cassignmentnode.create(
  572. ctemprefnode.create(calltempnode),
  573. p));
  574. p:=ctemprefnode.create(calltempnode);
  575. typecheckpass(p);
  576. end;
  577. { several object types have implicit dereferencing }
  578. { is_implicit_pointer_object_type() returns true for records
  579. on the JVM target because they are implemented as classes
  580. there, but we definitely have to take their address here
  581. since otherwise a deep copy is made and changes are made to
  582. this copy rather than to the original one }
  583. hasimplicitderef:=
  584. (is_implicit_pointer_object_type(p.resultdef) or
  585. (p.resultdef.typ=classrefdef)) and
  586. not((target_info.system in systems_jvm) and
  587. ((p.resultdef.typ=recorddef) or
  588. is_object(p.resultdef)));
  589. if hasimplicitderef then
  590. hdef:=p.resultdef
  591. else
  592. hdef:=cpointerdef.create(p.resultdef);
  593. { load address of the value in a temp }
  594. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  595. typecheckpass(tnode(tempnode));
  596. valuenode:=p;
  597. refnode:=ctemprefnode.create(tempnode);
  598. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  599. { add address call for valuenode and deref for refnode if this
  600. is not done implicitly }
  601. if not hasimplicitderef then
  602. begin
  603. valuenode:=caddrnode.create_internal_nomark(valuenode);
  604. include(valuenode.flags,nf_typedaddr);
  605. refnode:=cderefnode.create(refnode);
  606. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  607. end;
  608. addstatement(newstatement,tempnode);
  609. addstatement(newstatement,cassignmentnode.create(
  610. ctemprefnode.create(tempnode),
  611. valuenode));
  612. typecheckpass(refnode);
  613. end;
  614. { Note: the symtable of the helper is pushed after the following
  615. "case", the symtables of the helper's parents are passed in
  616. the "case" branches }
  617. withsymtablelist:=TFPObjectList.create(true);
  618. case p.resultdef.typ of
  619. objectdef :
  620. begin
  621. { do we have a helper for this type? }
  622. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  623. { push symtables of all parents in reverse order }
  624. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  625. { push symtables of all parents of the helper in reverse order }
  626. if assigned(helperdef) then
  627. pushobjchild(helperdef,helperdef.childof);
  628. { push object symtable }
  629. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  630. symtablestack.push(st);
  631. withsymtablelist.add(st);
  632. end;
  633. classrefdef :
  634. begin
  635. { do we have a helper for this type? }
  636. search_last_objectpascal_helper(tobjectdef(tclassrefdef(p.resultdef).pointeddef),current_structdef,helperdef);
  637. { push symtables of all parents in reverse order }
  638. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  639. { push symtables of all parents of the helper in reverse order }
  640. if assigned(helperdef) then
  641. pushobjchild(helperdef,helperdef.childof);
  642. { push object symtable }
  643. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  644. symtablestack.push(st);
  645. withsymtablelist.add(st);
  646. end;
  647. recorddef :
  648. begin
  649. { do we have a helper for this type? }
  650. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  651. { push symtables of all parents of the helper in reverse order }
  652. if assigned(helperdef) then
  653. pushobjchild(helperdef,helperdef.childof);
  654. { push record symtable }
  655. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  656. symtablestack.push(st);
  657. withsymtablelist.add(st);
  658. end;
  659. undefineddef :
  660. begin
  661. if not(df_generic in current_procinfo.procdef.defoptions) then
  662. internalerror(2012122802);
  663. helperdef:=nil;
  664. { push record symtable }
  665. st:=twithsymtable.create(p.resultdef,nil,refnode);
  666. symtablestack.push(st);
  667. withsymtablelist.add(st);
  668. end;
  669. else
  670. internalerror(200601271);
  671. end;
  672. { push helper symtable }
  673. if assigned(helperdef) then
  674. begin
  675. st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
  676. symtablestack.push(st);
  677. withsymtablelist.add(st);
  678. end;
  679. if try_to_consume(_COMMA) then
  680. p:=_with_statement()
  681. else
  682. begin
  683. consume(_DO);
  684. if token<>_SEMICOLON then
  685. p:=statement
  686. else
  687. p:=cnothingnode.create;
  688. end;
  689. { remove symtables in reverse order from the stack }
  690. for i:=withsymtablelist.count-1 downto 0 do
  691. symtablestack.pop(TSymtable(withsymtablelist[i]));
  692. withsymtablelist.free;
  693. // p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
  694. { Finalize complex withnode with destroy of temp }
  695. if assigned(newblock) then
  696. begin
  697. addstatement(newstatement,p);
  698. if assigned(tempnode) then
  699. addstatement(newstatement,ctempdeletenode.create(tempnode));
  700. if assigned(calltempnode) then
  701. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  702. p:=newblock;
  703. end;
  704. result:=p;
  705. end
  706. else
  707. begin
  708. p.free;
  709. Message1(parser_e_false_with_expr,p.resultdef.GetTypeName);
  710. { try to recover from error }
  711. if try_to_consume(_COMMA) then
  712. begin
  713. hp:=_with_statement();
  714. if (hp=nil) then; { remove warning about unused }
  715. end
  716. else
  717. begin
  718. consume(_DO);
  719. { ignore all }
  720. if token<>_SEMICOLON then
  721. statement;
  722. end;
  723. result:=nil;
  724. end;
  725. end;
  726. function with_statement : tnode;
  727. begin
  728. consume(_WITH);
  729. with_statement:=_with_statement();
  730. end;
  731. function raise_statement : tnode;
  732. var
  733. p,pobj,paddr,pframe : tnode;
  734. begin
  735. pobj:=nil;
  736. paddr:=nil;
  737. pframe:=nil;
  738. consume(_RAISE);
  739. if not(token in endtokens) then
  740. begin
  741. { object }
  742. pobj:=comp_expr([ef_accept_equal]);
  743. if try_to_consume(_AT) then
  744. begin
  745. paddr:=comp_expr([ef_accept_equal]);
  746. if try_to_consume(_COMMA) then
  747. pframe:=comp_expr([ef_accept_equal]);
  748. end;
  749. end
  750. else
  751. begin
  752. if (block_type<>bt_except) then
  753. Message(parser_e_no_reraise_possible);
  754. end;
  755. p:=craisenode.create(pobj,paddr,pframe);
  756. raise_statement:=p;
  757. end;
  758. function try_statement : tnode;
  759. procedure check_type_valid(var def: tdef);
  760. begin
  761. if not (is_class(def) or is_javaclass(def) or
  762. { skip showing error message the second time }
  763. (def.typ=errordef)) then
  764. begin
  765. Message1(type_e_class_type_expected,def.typename);
  766. def:=generrordef;
  767. end;
  768. end;
  769. var
  770. p_try_block,p_finally_block,first,last,
  771. p_default,p_specific,hp : tnode;
  772. ot : tDef;
  773. sym : tlocalvarsym;
  774. old_block_type : tblock_type;
  775. excepTSymtable : TSymtable;
  776. objname,objrealname : TIDString;
  777. srsym : tsym;
  778. srsymtable : TSymtable;
  779. t:ttoken;
  780. unit_found:boolean;
  781. oldcurrent_exceptblock: integer;
  782. begin
  783. p_default:=nil;
  784. p_specific:=nil;
  785. excepTSymtable:=nil;
  786. last:=nil;
  787. { read statements to try }
  788. consume(_TRY);
  789. first:=nil;
  790. inc(exceptblockcounter);
  791. oldcurrent_exceptblock := current_exceptblock;
  792. current_exceptblock := exceptblockcounter;
  793. old_block_type := block_type;
  794. block_type := bt_body;
  795. while (token<>_FINALLY) and (token<>_EXCEPT) do
  796. begin
  797. if first=nil then
  798. begin
  799. last:=cstatementnode.create(statement,nil);
  800. first:=last;
  801. end
  802. else
  803. begin
  804. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  805. last:=tstatementnode(last).right;
  806. end;
  807. if not try_to_consume(_SEMICOLON) then
  808. break;
  809. consume_emptystats;
  810. end;
  811. p_try_block:=cblocknode.create(first);
  812. if try_to_consume(_FINALLY) then
  813. begin
  814. inc(exceptblockcounter);
  815. current_exceptblock := exceptblockcounter;
  816. p_finally_block:=statements_til_end;
  817. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  818. end
  819. else
  820. begin
  821. consume(_EXCEPT);
  822. block_type:=bt_except;
  823. inc(exceptblockcounter);
  824. current_exceptblock := exceptblockcounter;
  825. ot:=generrordef;
  826. p_specific:=nil;
  827. if (idtoken=_ON) then
  828. { catch specific exceptions }
  829. begin
  830. repeat
  831. consume(_ON);
  832. if token=_ID then
  833. begin
  834. objname:=pattern;
  835. objrealname:=orgpattern;
  836. { can't use consume_sym here, because we need already
  837. to check for the colon }
  838. searchsym(objname,srsym,srsymtable);
  839. consume(_ID);
  840. { is a explicit name for the exception given ? }
  841. if try_to_consume(_COLON) then
  842. begin
  843. single_type(ot,[]);
  844. check_type_valid(ot);
  845. sym:=clocalvarsym.create(objrealname,vs_value,ot,[],true);
  846. end
  847. else
  848. begin
  849. { check if type is valid, must be done here because
  850. with "e: Exception" the e is not necessary }
  851. { support unit.identifier }
  852. unit_found:=try_consume_unitsym_no_specialize(srsym,srsymtable,t,false);
  853. if srsym=nil then
  854. begin
  855. identifier_not_found(orgpattern);
  856. srsym:=generrorsym;
  857. end;
  858. if unit_found then
  859. consume(t);
  860. { check if type is valid, must be done here because
  861. with "e: Exception" the e is not necessary }
  862. if (srsym.typ=typesym) then
  863. begin
  864. ot:=ttypesym(srsym).typedef;
  865. parse_nested_types(ot,false,false,nil);
  866. check_type_valid(ot);
  867. end
  868. else
  869. begin
  870. Message(type_e_type_id_expected);
  871. ot:=generrordef;
  872. end;
  873. { create dummy symbol so we don't need a special
  874. case in ncgflw, and so that we always know the
  875. type }
  876. sym:=clocalvarsym.create('$exceptsym',vs_value,ot,[],true);
  877. end;
  878. excepTSymtable:=tstt_excepTSymtable.create;
  879. excepTSymtable.insert(sym);
  880. symtablestack.push(excepTSymtable);
  881. end
  882. else
  883. consume(_ID);
  884. consume(_DO);
  885. hp:=connode.create(nil,statement);
  886. if ot.typ=errordef then
  887. begin
  888. hp.free;
  889. hp:=cerrornode.create;
  890. end;
  891. if p_specific=nil then
  892. begin
  893. last:=hp;
  894. p_specific:=last;
  895. end
  896. else
  897. begin
  898. tonnode(last).left:=hp;
  899. last:=tonnode(last).left;
  900. end;
  901. { set the informations }
  902. { only if the creation of the onnode was succesful, it's possible }
  903. { that last and hp are errornodes (JM) }
  904. if last.nodetype = onn then
  905. begin
  906. tonnode(last).excepttype:=tobjectdef(ot);
  907. tonnode(last).excepTSymtable:=excepTSymtable;
  908. end;
  909. { remove exception symtable }
  910. if assigned(excepTSymtable) then
  911. begin
  912. symtablestack.pop(excepTSymtable);
  913. if last.nodetype <> onn then
  914. excepTSymtable.free;
  915. end;
  916. if not try_to_consume(_SEMICOLON) then
  917. break;
  918. consume_emptystats;
  919. until (token in [_END,_ELSE]);
  920. if try_to_consume(_ELSE) then
  921. begin
  922. { catch the other exceptions }
  923. p_default:=statements_til_end;
  924. end
  925. else
  926. consume(_END);
  927. end
  928. else
  929. begin
  930. { catch all exceptions }
  931. p_default:=statements_til_end;
  932. end;
  933. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  934. end;
  935. block_type:=old_block_type;
  936. current_exceptblock := oldcurrent_exceptblock;
  937. end;
  938. function _asm_statement : tnode;
  939. var
  940. asmstat : tasmnode;
  941. reg : tregister;
  942. asmreader : tbaseasmreader;
  943. entrypos : tfileposinfo;
  944. hl : TAsmList;
  945. begin
  946. Inside_asm_statement:=true;
  947. asmstat:=nil;
  948. hl:=nil;
  949. if assigned(asmmodeinfos[current_settings.asmmode]) then
  950. begin
  951. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  952. entrypos:=current_filepos;
  953. hl:=asmreader.assemble as TAsmList;
  954. if (not hl.empty) then
  955. begin
  956. { mark boundaries of assembler block, this is necessary for optimizer }
  957. hl.insert(tai_marker.create(mark_asmblockstart));
  958. hl.concat(tai_marker.create(mark_asmblockend));
  959. end;
  960. asmstat:=casmnode.create(hl);
  961. asmstat.fileinfo:=entrypos;
  962. asmreader.free;
  963. end
  964. else
  965. Message(parser_f_assembler_reader_not_supported);
  966. { Mark procedure that it has assembler blocks }
  967. include(current_procinfo.flags,pi_has_assembler_block);
  968. { Read first the _ASM statement }
  969. consume(_ASM);
  970. { Force an empty register list for pure assembler routines,
  971. so that pass2 won't allocate volatile registers for them. }
  972. asmstat.has_registerlist:=(po_assembler in current_procinfo.procdef.procoptions);
  973. { END is read, got a list of changed registers? }
  974. if try_to_consume(_LECKKLAMMER) then
  975. begin
  976. if token<>_RECKKLAMMER then
  977. begin
  978. if po_assembler in current_procinfo.procdef.procoptions then
  979. Message(parser_w_register_list_ignored);
  980. repeat
  981. { it's possible to specify the modified registers }
  982. reg:=std_regnum_search(lower(cstringpattern));
  983. if reg<>NR_NO then
  984. begin
  985. if not(po_assembler in current_procinfo.procdef.procoptions) and assigned(hl) then
  986. begin
  987. hl.Insert(tai_regalloc.alloc(reg,nil));
  988. hl.Insert(tai_regalloc.markused(reg));
  989. hl.Concat(tai_regalloc.dealloc(reg,nil));
  990. end;
  991. end
  992. else
  993. Message(asmr_e_invalid_register);
  994. consume(_CSTRING);
  995. if not try_to_consume(_COMMA) then
  996. break;
  997. until false;
  998. asmstat.has_registerlist:=true;
  999. end;
  1000. consume(_RECKKLAMMER);
  1001. end;
  1002. Inside_asm_statement:=false;
  1003. _asm_statement:=asmstat;
  1004. end;
  1005. function statement : tnode;
  1006. var
  1007. p,
  1008. code : tnode;
  1009. filepos : tfileposinfo;
  1010. srsym : tsym;
  1011. srsymtable : TSymtable;
  1012. s : TIDString;
  1013. begin
  1014. filepos:=current_tokenpos;
  1015. code:=nil;
  1016. case token of
  1017. _GOTO :
  1018. begin
  1019. if not(cs_support_goto in current_settings.moduleswitches) then
  1020. Message(sym_e_goto_and_label_not_supported);
  1021. consume(_GOTO);
  1022. if (token<>_INTCONST) and (token<>_ID) then
  1023. begin
  1024. Message(sym_e_label_not_found);
  1025. code:=cerrornode.create;
  1026. end
  1027. else
  1028. begin
  1029. if token=_ID then
  1030. consume_sym(srsym,srsymtable)
  1031. else
  1032. begin
  1033. if token<>_INTCONST then
  1034. internalerror(201008021);
  1035. { strip leading 0's in iso mode }
  1036. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  1037. while pattern[1]='0' do
  1038. delete(pattern,1,1);
  1039. searchsym(pattern,srsym,srsymtable);
  1040. if srsym=nil then
  1041. begin
  1042. identifier_not_found(pattern);
  1043. srsym:=generrorsym;
  1044. srsymtable:=nil;
  1045. end;
  1046. consume(token);
  1047. end;
  1048. if srsym.typ<>labelsym then
  1049. begin
  1050. Message(sym_e_id_is_no_label_id);
  1051. code:=cerrornode.create;
  1052. end
  1053. else
  1054. begin
  1055. { goto outside the current scope? }
  1056. if srsym.owner<>current_procinfo.procdef.localst then
  1057. begin
  1058. { allowed? }
  1059. if not(m_non_local_goto in current_settings.modeswitches) then
  1060. Message(parser_e_goto_outside_proc);
  1061. include(current_procinfo.flags,pi_has_global_goto);
  1062. end;
  1063. code:=cgotonode.create(tlabelsym(srsym));
  1064. tgotonode(code).labelsym:=tlabelsym(srsym);
  1065. { set flag that this label is used }
  1066. tlabelsym(srsym).used:=true;
  1067. end;
  1068. end;
  1069. end;
  1070. _BEGIN :
  1071. code:=statement_block(_BEGIN);
  1072. _IF :
  1073. code:=if_statement;
  1074. _CASE :
  1075. code:=case_statement;
  1076. _REPEAT :
  1077. code:=repeat_statement;
  1078. _WHILE :
  1079. code:=while_statement;
  1080. _FOR :
  1081. code:=for_statement;
  1082. _WITH :
  1083. code:=with_statement;
  1084. _TRY :
  1085. code:=try_statement;
  1086. _RAISE :
  1087. code:=raise_statement;
  1088. { semicolons,else until and end are ignored }
  1089. _SEMICOLON,
  1090. _ELSE,
  1091. _UNTIL,
  1092. _END:
  1093. code:=cnothingnode.create;
  1094. _FAIL :
  1095. begin
  1096. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1097. Message(parser_e_fail_only_in_constructor);
  1098. consume(_FAIL);
  1099. code:=cnodeutils.call_fail_node;
  1100. end;
  1101. _ASM :
  1102. begin
  1103. if parse_generic then
  1104. Message(parser_e_no_assembler_in_generic);
  1105. code:=_asm_statement;
  1106. end;
  1107. _EOF :
  1108. Message(scan_f_end_of_file);
  1109. else
  1110. begin
  1111. { don't typecheck yet, because that will also simplify, which may
  1112. result in not detecting certain kinds of syntax errors --
  1113. see mantis #15594 }
  1114. p:=expr(false);
  1115. { save the pattern here for latter usage, the label could be "000",
  1116. even if we read an expression, the pattern is still valid if it's really
  1117. a label (FK)
  1118. if you want to mess here, take care of
  1119. tests/webtbs/tw3546.pp
  1120. }
  1121. s:=pattern;
  1122. { When a colon follows a intconst then transform it into a label }
  1123. if (p.nodetype=ordconstn) and
  1124. try_to_consume(_COLON) then
  1125. begin
  1126. { in iso mode, 0003: is equal to 3: }
  1127. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  1128. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1129. else
  1130. searchsym(s,srsym,srsymtable);
  1131. p.free;
  1132. if assigned(srsym) and
  1133. (srsym.typ=labelsym) then
  1134. begin
  1135. if tlabelsym(srsym).defined then
  1136. Message(sym_e_label_already_defined);
  1137. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1138. begin
  1139. tlabelsym(srsym).nonlocal:=true;
  1140. exclude(current_procinfo.procdef.procoptions,po_inline);
  1141. end;
  1142. if tlabelsym(srsym).nonlocal and
  1143. (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1144. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1145. tlabelsym(srsym).defined:=true;
  1146. p:=clabelnode.create(nil,tlabelsym(srsym));
  1147. tlabelsym(srsym).code:=p;
  1148. end
  1149. else
  1150. begin
  1151. Message1(sym_e_label_used_and_not_defined,s);
  1152. p:=cnothingnode.create;
  1153. end;
  1154. end;
  1155. if p.nodetype=labeln then
  1156. begin
  1157. { the pointer to the following instruction }
  1158. { isn't a very clean way }
  1159. if token in endtokens then
  1160. tlabelnode(p).left:=cnothingnode.create
  1161. else
  1162. tlabelnode(p).left:=statement();
  1163. { be sure to have left also typecheckpass }
  1164. typecheckpass(tlabelnode(p).left);
  1165. end
  1166. else
  1167. { change a load of a procvar to a call. this is also
  1168. supported in fpc mode }
  1169. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1170. maybe_call_procvar(p,false);
  1171. { blockn support because a read/write is changed into a blocknode
  1172. with a separate statement for each read/write operation (JM)
  1173. the same is true for val() if the third parameter is not 32 bit
  1174. goto nodes are created by the compiler for non local exit statements, so
  1175. include them as well
  1176. }
  1177. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1178. continuen,labeln,blockn,exitn,goton]) or
  1179. ((p.nodetype=inlinen) and
  1180. not is_void(p.resultdef)) or
  1181. ((p.nodetype=calln) and
  1182. (assigned(tcallnode(p).procdefinition)) and
  1183. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1184. Message(parser_e_illegal_expression);
  1185. if not assigned(p.resultdef) then
  1186. do_typecheckpass(p);
  1187. { Specify that we don't use the value returned by the call.
  1188. This is used for :
  1189. - dispose of temp stack space
  1190. - dispose on FPU stack
  1191. - extended syntax checking }
  1192. if (p.nodetype=calln) then
  1193. begin
  1194. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1195. { in $x- state, the function result must not be ignored }
  1196. if not(cs_extsyntax in current_settings.moduleswitches) and
  1197. not(is_void(p.resultdef)) and
  1198. { can be nil in case there was an error in the expression }
  1199. assigned(tcallnode(p).procdefinition) and
  1200. { allow constructor calls to drop the result if they are
  1201. called as instance methods instead of class methods }
  1202. not(
  1203. (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1204. is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
  1205. assigned(tcallnode(p).methodpointer) and
  1206. (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
  1207. ) then
  1208. Message(parser_e_illegal_expression);
  1209. end;
  1210. code:=p;
  1211. end;
  1212. end;
  1213. if assigned(code) then
  1214. begin
  1215. typecheckpass(code);
  1216. code.fileinfo:=filepos;
  1217. end;
  1218. statement:=code;
  1219. end;
  1220. function statement_block(starttoken : ttoken) : tnode;
  1221. var
  1222. first,last : tnode;
  1223. filepos : tfileposinfo;
  1224. begin
  1225. first:=nil;
  1226. last:=nil;
  1227. filepos:=current_tokenpos;
  1228. consume(starttoken);
  1229. while not((token=_END) or (token=_FINALIZATION)) do
  1230. begin
  1231. if first=nil then
  1232. begin
  1233. last:=cstatementnode.create(statement,nil);
  1234. first:=last;
  1235. end
  1236. else
  1237. begin
  1238. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1239. last:=tstatementnode(last).right;
  1240. end;
  1241. if ((token=_END) or (token=_FINALIZATION)) then
  1242. break
  1243. else
  1244. begin
  1245. { if no semicolon, then error and go on }
  1246. if token<>_SEMICOLON then
  1247. begin
  1248. consume(_SEMICOLON);
  1249. consume_all_until(_SEMICOLON);
  1250. end;
  1251. consume(_SEMICOLON);
  1252. end;
  1253. consume_emptystats;
  1254. end;
  1255. { don't consume the finalization token, it is consumed when
  1256. reading the finalization block, but allow it only after
  1257. an initalization ! }
  1258. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1259. consume(_END);
  1260. last:=cblocknode.create(first);
  1261. last.fileinfo:=filepos;
  1262. statement_block:=last;
  1263. end;
  1264. function assembler_block : tnode;
  1265. var
  1266. p : tnode;
  1267. {$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1268. locals : longint;
  1269. {$endif}
  1270. srsym : tsym;
  1271. begin
  1272. if parse_generic then
  1273. message(parser_e_no_assembler_in_generic);
  1274. { Rename the funcret so that recursive calls are possible }
  1275. if not is_void(current_procinfo.procdef.returndef) then
  1276. begin
  1277. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1278. if assigned(srsym) then
  1279. srsym.realname:='$hiddenresult';
  1280. end;
  1281. { delphi uses register calling for assembler methods }
  1282. if (m_delphi in current_settings.modeswitches) and
  1283. (po_assembler in current_procinfo.procdef.procoptions) and
  1284. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1285. current_procinfo.procdef.proccalloption:=pocall_register;
  1286. { force the asm statement }
  1287. if token<>_ASM then
  1288. consume(_ASM);
  1289. include(current_procinfo.flags,pi_is_assembler);
  1290. p:=_asm_statement;
  1291. {$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1292. if (po_assembler in current_procinfo.procdef.procoptions) then
  1293. begin
  1294. { set the framepointer to esp for assembler functions when the
  1295. following conditions are met:
  1296. - if the are no local variables and parameters (except the allocated result)
  1297. - no reference to the result variable (refcount<=1)
  1298. - result is not stored as parameter
  1299. - target processor has optional frame pointer save
  1300. (vm, i386, vm only currently)
  1301. }
  1302. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1303. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1304. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1305. if (locals=0) and
  1306. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1307. (not assigned(current_procinfo.procdef.funcretsym) or
  1308. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1309. not (df_generic in current_procinfo.procdef.defoptions) and
  1310. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1311. begin
  1312. { Only need to set the framepointer, the locals will
  1313. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1314. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1315. end;
  1316. end;
  1317. {$endif not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) not(defined(mipsel))}
  1318. { Flag the result as assigned when it is returned in a
  1319. register.
  1320. }
  1321. if assigned(current_procinfo.procdef.funcretsym) and
  1322. not (df_generic in current_procinfo.procdef.defoptions) and
  1323. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1324. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1325. { because the END is already read we need to get the
  1326. last_endtoken_filepos here (PFV) }
  1327. last_endtoken_filepos:=current_tokenpos;
  1328. assembler_block:=p;
  1329. end;
  1330. end.