pstatmnt.pas 56 KB

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