pstatmnt.pas 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472
  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,aasmbase,aasmtai,aasmdata,
  34. { symtable }
  35. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  36. paramgr,symutil,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nutils,ngenutil,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,ptype,pexpr,
  43. { codegen }
  44. procinfo,cgbase,
  45. { assembler reader }
  46. rabase,
  47. { wide- and unicodestrings}
  48. widestr
  49. ;
  50. function statement : tnode;forward;
  51. function if_statement : tnode;
  52. var
  53. ex,if_a,else_a : tnode;
  54. begin
  55. consume(_IF);
  56. ex:=comp_expr(true,false);
  57. consume(_THEN);
  58. if not(token in endtokens) then
  59. if_a:=statement
  60. else
  61. if_a:=nil;
  62. if try_to_consume(_ELSE) then
  63. else_a:=statement
  64. else
  65. else_a:=nil;
  66. result:=cifnode.create(ex,if_a,else_a);
  67. end;
  68. { creates a block (list) of statements, til the next END token }
  69. function statements_til_end : tnode;
  70. var
  71. first,last : tstatementnode;
  72. begin
  73. first:=nil;
  74. last:=nil;
  75. while token<>_END do
  76. begin
  77. if first=nil then
  78. begin
  79. last:=cstatementnode.create(statement,nil);
  80. first:=last;
  81. end
  82. else
  83. begin
  84. last.right:=cstatementnode.create(statement,nil);
  85. last:=tstatementnode(last.right);
  86. end;
  87. if not try_to_consume(_SEMICOLON) then
  88. break;
  89. consume_emptystats;
  90. end;
  91. consume(_END);
  92. statements_til_end:=cblocknode.create(first);
  93. end;
  94. function case_statement : tnode;
  95. var
  96. casedef : tdef;
  97. caseexpr,p : tnode;
  98. blockid : longint;
  99. hl1,hl2 : TConstExprInt;
  100. sl1,sl2 : tstringconstnode;
  101. casedeferror, caseofstring : boolean;
  102. casenode : tcasenode;
  103. begin
  104. consume(_CASE);
  105. caseexpr:=comp_expr(true,false);
  106. { determines result type }
  107. do_typecheckpass(caseexpr);
  108. { variants must be accepted, but first they must be converted to integer }
  109. if caseexpr.resultdef.typ=variantdef then
  110. begin
  111. caseexpr:=ctypeconvnode.create_internal(caseexpr,sinttype);
  112. do_typecheckpass(caseexpr);
  113. end;
  114. set_varstate(caseexpr,vs_read,[vsf_must_be_valid]);
  115. casedeferror:=false;
  116. casedef:=caseexpr.resultdef;
  117. { case of string must be rejected in delphi-, }
  118. { tp7/bp7-, mac-compatibility modes. }
  119. caseofstring :=
  120. ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and
  121. is_string(casedef);
  122. if (not assigned(casedef)) or
  123. ( not(is_ordinal(casedef)) and (not caseofstring) ) then
  124. begin
  125. CGMessage(type_e_ordinal_or_string_expr_expected);
  126. { create a correct tree }
  127. caseexpr.free;
  128. caseexpr:=cordconstnode.create(0,u32inttype,false);
  129. { set error flag so no rangechecks are done }
  130. casedeferror:=true;
  131. end;
  132. { Create casenode }
  133. casenode:=ccasenode.create(caseexpr);
  134. consume(_OF);
  135. { Parse all case blocks }
  136. blockid:=0;
  137. repeat
  138. { maybe an instruction has more case labels }
  139. repeat
  140. p:=expr(true);
  141. if is_widechar(casedef) then
  142. begin
  143. if (p.nodetype=rangen) then
  144. begin
  145. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  146. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  147. do_typecheckpass(trangenode(p).left);
  148. do_typecheckpass(trangenode(p).right);
  149. end
  150. else
  151. begin
  152. p:=ctypeconvnode.create(p,cwidechartype);
  153. do_typecheckpass(p);
  154. end;
  155. end
  156. else
  157. begin
  158. if is_char(casedef) and is_widechar(p.resultdef) then
  159. begin
  160. if (p.nodetype=ordconstn) then
  161. begin
  162. p:=ctypeconvnode.create(p,cansichartype);
  163. do_typecheckpass(p);
  164. end
  165. else if (p.nodetype=rangen) then
  166. begin
  167. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cansichartype);
  168. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cansichartype);
  169. do_typecheckpass(trangenode(p).left);
  170. do_typecheckpass(trangenode(p).right);
  171. end;
  172. end;
  173. end;
  174. hl1:=0;
  175. hl2:=0;
  176. sl1:=nil;
  177. sl2:=nil;
  178. if (p.nodetype=rangen) then
  179. begin
  180. { type check for string case statements }
  181. if caseofstring and
  182. is_conststring_or_constcharnode(trangenode(p).left) and
  183. is_conststring_or_constcharnode(trangenode(p).right) then
  184. begin
  185. { we need stringconstnodes, even if expression contains single chars }
  186. sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
  187. sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
  188. if sl1.fullcompare(sl2) > 0 then
  189. CGMessage(parser_e_case_lower_less_than_upper_bound);
  190. end
  191. { type checking for ordinal case statements }
  192. else if (not caseofstring) and
  193. is_subequal(casedef, trangenode(p).left.resultdef) and
  194. is_subequal(casedef, trangenode(p).right.resultdef) then
  195. begin
  196. hl1:=get_ordinal_value(trangenode(p).left);
  197. hl2:=get_ordinal_value(trangenode(p).right);
  198. if hl1>hl2 then
  199. CGMessage(parser_e_case_lower_less_than_upper_bound);
  200. if not casedeferror then
  201. begin
  202. testrange(casedef,hl1,false,false);
  203. testrange(casedef,hl2,false,false);
  204. end;
  205. end
  206. else
  207. CGMessage(parser_e_case_mismatch);
  208. if caseofstring then
  209. casenode.addlabel(blockid,sl1,sl2)
  210. else
  211. casenode.addlabel(blockid,hl1,hl2);
  212. end
  213. else
  214. begin
  215. { type check for string case statements }
  216. if (caseofstring and (not is_conststring_or_constcharnode(p))) or
  217. { type checking for ordinal case statements }
  218. ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
  219. CGMessage(parser_e_case_mismatch);
  220. if caseofstring then
  221. begin
  222. sl1:=get_string_value(p, tstringdef(casedef));
  223. casenode.addlabel(blockid,sl1,sl1);
  224. end
  225. else
  226. begin
  227. hl1:=get_ordinal_value(p);
  228. if not casedeferror then
  229. testrange(casedef,hl1,false,false);
  230. casenode.addlabel(blockid,hl1,hl1);
  231. end;
  232. end;
  233. p.free;
  234. sl1.free;
  235. sl2.free;
  236. if token=_COMMA then
  237. consume(_COMMA)
  238. else
  239. break;
  240. until false;
  241. consume(_COLON);
  242. { add instruction block }
  243. casenode.addblock(blockid,statement);
  244. { next block }
  245. inc(blockid);
  246. if not(token in [_ELSE,_OTHERWISE,_END]) then
  247. consume(_SEMICOLON);
  248. until (token in [_ELSE,_OTHERWISE,_END]);
  249. if (token in [_ELSE,_OTHERWISE]) then
  250. begin
  251. if not try_to_consume(_ELSE) then
  252. consume(_OTHERWISE);
  253. casenode.addelseblock(statements_til_end);
  254. end
  255. else
  256. consume(_END);
  257. result:=casenode;
  258. end;
  259. function repeat_statement : tnode;
  260. var
  261. first,last,p_e : tnode;
  262. begin
  263. consume(_REPEAT);
  264. first:=nil;
  265. last:=nil;
  266. while token<>_UNTIL do
  267. begin
  268. if first=nil then
  269. begin
  270. last:=cstatementnode.create(statement,nil);
  271. first:=last;
  272. end
  273. else
  274. begin
  275. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  276. last:=tstatementnode(last).right;
  277. end;
  278. if not try_to_consume(_SEMICOLON) then
  279. break;
  280. consume_emptystats;
  281. end;
  282. consume(_UNTIL);
  283. first:=cblocknode.create(first);
  284. p_e:=comp_expr(true,false);
  285. result:=cwhilerepeatnode.create(p_e,first,false,true);
  286. end;
  287. function while_statement : tnode;
  288. var
  289. p_e,p_a : tnode;
  290. begin
  291. consume(_WHILE);
  292. p_e:=comp_expr(true,false);
  293. consume(_DO);
  294. p_a:=statement;
  295. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  296. end;
  297. { a helper function which is used both by "with" and "for-in loop" nodes }
  298. function skip_nodes_before_load(p: tnode): tnode;
  299. begin
  300. { ignore nodes that don't add instructions in the tree }
  301. while assigned(p) and
  302. { equal type conversions }
  303. (
  304. (p.nodetype=typeconvn) and
  305. (ttypeconvnode(p).convtype=tc_equal)
  306. ) or
  307. { constant array index }
  308. (
  309. (p.nodetype=vecn) and
  310. (tvecnode(p).right.nodetype=ordconstn)
  311. ) do
  312. p:=tunarynode(p).left;
  313. result:=p;
  314. end;
  315. function for_statement : tnode;
  316. procedure check_range(hp:tnode; fordef: tdef);
  317. begin
  318. if (hp.nodetype=ordconstn) and
  319. (fordef.typ<>errordef) then
  320. testrange(fordef,tordconstnode(hp).value,false,true);
  321. end;
  322. function for_loop_create(hloopvar: tnode): tnode;
  323. var
  324. hp,
  325. hblock,
  326. hto,hfrom : tnode;
  327. backward : boolean;
  328. loopvarsym : tabstractvarsym;
  329. begin
  330. { Check loop variable }
  331. loopvarsym:=nil;
  332. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  333. if not(is_ordinal(hloopvar.resultdef))
  334. {$ifndef cpu64bitaddr}
  335. or is_64bitint(hloopvar.resultdef)
  336. {$endif not cpu64bitaddr}
  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(true,false);
  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(true,false);
  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(true,false);
  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,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(true,false);
  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(valuenode.flags,nf_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. // p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
  697. { Finalize complex withnode with destroy of temp }
  698. if assigned(newblock) then
  699. begin
  700. addstatement(newstatement,p);
  701. if assigned(tempnode) then
  702. addstatement(newstatement,ctempdeletenode.create(tempnode));
  703. if assigned(calltempnode) then
  704. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  705. p:=newblock;
  706. end;
  707. result:=p;
  708. end
  709. else
  710. begin
  711. p.free;
  712. Message1(parser_e_false_with_expr,p.resultdef.GetTypeName);
  713. { try to recover from error }
  714. if try_to_consume(_COMMA) then
  715. begin
  716. hp:=_with_statement();
  717. if (hp=nil) then; { remove warning about unused }
  718. end
  719. else
  720. begin
  721. consume(_DO);
  722. { ignore all }
  723. if token<>_SEMICOLON then
  724. statement;
  725. end;
  726. result:=nil;
  727. end;
  728. end;
  729. function with_statement : tnode;
  730. begin
  731. consume(_WITH);
  732. with_statement:=_with_statement();
  733. end;
  734. function raise_statement : tnode;
  735. var
  736. p,pobj,paddr,pframe : tnode;
  737. begin
  738. pobj:=nil;
  739. paddr:=nil;
  740. pframe:=nil;
  741. consume(_RAISE);
  742. if not(token in endtokens) then
  743. begin
  744. { object }
  745. pobj:=comp_expr(true,false);
  746. if try_to_consume(_AT) then
  747. begin
  748. paddr:=comp_expr(true,false);
  749. if try_to_consume(_COMMA) then
  750. pframe:=comp_expr(true,false);
  751. end;
  752. end
  753. else
  754. begin
  755. if (block_type<>bt_except) then
  756. Message(parser_e_no_reraise_possible);
  757. end;
  758. p:=craisenode.create(pobj,paddr,pframe);
  759. raise_statement:=p;
  760. end;
  761. function try_statement : tnode;
  762. procedure check_type_valid(var def: tdef);
  763. begin
  764. if not (is_class(def) or is_javaclass(def) or
  765. { skip showing error message the second time }
  766. (def.typ=errordef)) then
  767. begin
  768. Message1(type_e_class_type_expected,def.typename);
  769. def:=generrordef;
  770. end;
  771. end;
  772. var
  773. p_try_block,p_finally_block,first,last,
  774. p_default,p_specific,hp : tnode;
  775. ot : tDef;
  776. sym : tlocalvarsym;
  777. old_block_type : tblock_type;
  778. excepTSymtable : TSymtable;
  779. objname,objrealname : TIDString;
  780. srsym : tsym;
  781. srsymtable : TSymtable;
  782. t:ttoken;
  783. unit_found:boolean;
  784. oldcurrent_exceptblock: integer;
  785. begin
  786. p_default:=nil;
  787. p_specific:=nil;
  788. excepTSymtable:=nil;
  789. last:=nil;
  790. { read statements to try }
  791. consume(_TRY);
  792. first:=nil;
  793. inc(exceptblockcounter);
  794. oldcurrent_exceptblock := current_exceptblock;
  795. current_exceptblock := exceptblockcounter;
  796. old_block_type := block_type;
  797. block_type := bt_body;
  798. while (token<>_FINALLY) and (token<>_EXCEPT) do
  799. begin
  800. if first=nil then
  801. begin
  802. last:=cstatementnode.create(statement,nil);
  803. first:=last;
  804. end
  805. else
  806. begin
  807. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  808. last:=tstatementnode(last).right;
  809. end;
  810. if not try_to_consume(_SEMICOLON) then
  811. break;
  812. consume_emptystats;
  813. end;
  814. p_try_block:=cblocknode.create(first);
  815. if try_to_consume(_FINALLY) then
  816. begin
  817. inc(exceptblockcounter);
  818. current_exceptblock := exceptblockcounter;
  819. p_finally_block:=statements_til_end;
  820. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  821. end
  822. else
  823. begin
  824. consume(_EXCEPT);
  825. block_type:=bt_except;
  826. inc(exceptblockcounter);
  827. current_exceptblock := exceptblockcounter;
  828. ot:=generrordef;
  829. p_specific:=nil;
  830. if (idtoken=_ON) then
  831. { catch specific exceptions }
  832. begin
  833. repeat
  834. consume(_ON);
  835. if token=_ID then
  836. begin
  837. objname:=pattern;
  838. objrealname:=orgpattern;
  839. { can't use consume_sym here, because we need already
  840. to check for the colon }
  841. searchsym(objname,srsym,srsymtable);
  842. consume(_ID);
  843. { is a explicit name for the exception given ? }
  844. if try_to_consume(_COLON) then
  845. begin
  846. single_type(ot,[]);
  847. check_type_valid(ot);
  848. sym:=clocalvarsym.create(objrealname,vs_value,ot,[]);
  849. end
  850. else
  851. begin
  852. { check if type is valid, must be done here because
  853. with "e: Exception" the e is not necessary }
  854. { support unit.identifier }
  855. unit_found:=try_consume_unitsym(srsym,srsymtable,t,false);
  856. if srsym=nil then
  857. begin
  858. identifier_not_found(orgpattern);
  859. srsym:=generrorsym;
  860. end;
  861. if unit_found then
  862. consume(t);
  863. { check if type is valid, must be done here because
  864. with "e: Exception" the e is not necessary }
  865. if (srsym.typ=typesym) then
  866. begin
  867. ot:=ttypesym(srsym).typedef;
  868. parse_nested_types(ot,false,nil);
  869. check_type_valid(ot);
  870. end
  871. else
  872. begin
  873. Message(type_e_type_id_expected);
  874. ot:=generrordef;
  875. end;
  876. { create dummy symbol so we don't need a special
  877. case in ncgflw, and so that we always know the
  878. type }
  879. sym:=clocalvarsym.create('$exceptsym',vs_value,ot,[]);
  880. end;
  881. excepTSymtable:=tstt_excepTSymtable.create;
  882. excepTSymtable.insert(sym);
  883. symtablestack.push(excepTSymtable);
  884. end
  885. else
  886. consume(_ID);
  887. consume(_DO);
  888. hp:=connode.create(nil,statement);
  889. if ot.typ=errordef then
  890. begin
  891. hp.free;
  892. hp:=cerrornode.create;
  893. end;
  894. if p_specific=nil then
  895. begin
  896. last:=hp;
  897. p_specific:=last;
  898. end
  899. else
  900. begin
  901. tonnode(last).left:=hp;
  902. last:=tonnode(last).left;
  903. end;
  904. { set the informations }
  905. { only if the creation of the onnode was succesful, it's possible }
  906. { that last and hp are errornodes (JM) }
  907. if last.nodetype = onn then
  908. begin
  909. tonnode(last).excepttype:=tobjectdef(ot);
  910. tonnode(last).excepTSymtable:=excepTSymtable;
  911. end;
  912. { remove exception symtable }
  913. if assigned(excepTSymtable) then
  914. begin
  915. symtablestack.pop(excepTSymtable);
  916. if last.nodetype <> onn then
  917. excepTSymtable.free;
  918. end;
  919. if not try_to_consume(_SEMICOLON) then
  920. break;
  921. consume_emptystats;
  922. until (token in [_END,_ELSE]);
  923. if try_to_consume(_ELSE) then
  924. begin
  925. { catch the other exceptions }
  926. p_default:=statements_til_end;
  927. end
  928. else
  929. consume(_END);
  930. end
  931. else
  932. begin
  933. { catch all exceptions }
  934. p_default:=statements_til_end;
  935. end;
  936. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  937. end;
  938. block_type:=old_block_type;
  939. current_exceptblock := oldcurrent_exceptblock;
  940. end;
  941. function _asm_statement : tnode;
  942. var
  943. asmstat : tasmnode;
  944. Marker : tai;
  945. reg : tregister;
  946. asmreader : tbaseasmreader;
  947. entrypos : tfileposinfo;
  948. begin
  949. Inside_asm_statement:=true;
  950. asmstat:=nil;
  951. if assigned(asmmodeinfos[current_settings.asmmode]) then
  952. begin
  953. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  954. entrypos:=current_filepos;
  955. asmstat:=casmnode.create(asmreader.assemble as TAsmList);
  956. asmstat.fileinfo:=entrypos;
  957. asmreader.free;
  958. end
  959. else
  960. Message(parser_f_assembler_reader_not_supported);
  961. { Mark procedure that it has assembler blocks }
  962. include(current_procinfo.flags,pi_has_assembler_block);
  963. { Read first the _ASM statement }
  964. consume(_ASM);
  965. { END is read, got a list of changed registers? }
  966. if try_to_consume(_LECKKLAMMER) then
  967. begin
  968. {$ifdef cpunofpu}
  969. asmstat.used_regs_fpu:=[0..first_int_imreg-1];
  970. {$else cpunofpu}
  971. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  972. {$endif cpunofpu}
  973. if token<>_RECKKLAMMER then
  974. begin
  975. if po_assembler in current_procinfo.procdef.procoptions then
  976. Message(parser_w_register_list_ignored);
  977. repeat
  978. { it's possible to specify the modified registers }
  979. reg:=std_regnum_search(lower(cstringpattern));
  980. if reg<>NR_NO then
  981. begin
  982. if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
  983. include(asmstat.used_regs_int,getsupreg(reg));
  984. end
  985. else
  986. Message(asmr_e_invalid_register);
  987. consume(_CSTRING);
  988. if not try_to_consume(_COMMA) then
  989. break;
  990. until false;
  991. end;
  992. consume(_RECKKLAMMER);
  993. end
  994. else
  995. begin
  996. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  997. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  998. end;
  999. { mark the start and the end of the assembler block
  1000. this is needed for the optimizer }
  1001. If Assigned(AsmStat.p_asm) Then
  1002. Begin
  1003. Marker := Tai_Marker.Create(mark_AsmBlockStart);
  1004. AsmStat.p_asm.Insert(Marker);
  1005. Marker := Tai_Marker.Create(mark_AsmBlockEnd);
  1006. AsmStat.p_asm.Concat(Marker);
  1007. End;
  1008. Inside_asm_statement:=false;
  1009. _asm_statement:=asmstat;
  1010. end;
  1011. function statement : tnode;
  1012. var
  1013. p,
  1014. code : tnode;
  1015. filepos : tfileposinfo;
  1016. srsym : tsym;
  1017. srsymtable : TSymtable;
  1018. s : TIDString;
  1019. begin
  1020. filepos:=current_tokenpos;
  1021. code:=nil;
  1022. case token of
  1023. _GOTO :
  1024. begin
  1025. if not(cs_support_goto in current_settings.moduleswitches) then
  1026. Message(sym_e_goto_and_label_not_supported);
  1027. consume(_GOTO);
  1028. if (token<>_INTCONST) and (token<>_ID) then
  1029. begin
  1030. Message(sym_e_label_not_found);
  1031. code:=cerrornode.create;
  1032. end
  1033. else
  1034. begin
  1035. if token=_ID then
  1036. consume_sym(srsym,srsymtable)
  1037. else
  1038. begin
  1039. if token<>_INTCONST then
  1040. internalerror(201008021);
  1041. { strip leading 0's in iso mode }
  1042. if m_iso in current_settings.modeswitches then
  1043. while pattern[1]='0' do
  1044. delete(pattern,1,1);
  1045. searchsym(pattern,srsym,srsymtable);
  1046. if srsym=nil then
  1047. begin
  1048. identifier_not_found(pattern);
  1049. srsym:=generrorsym;
  1050. srsymtable:=nil;
  1051. end;
  1052. consume(token);
  1053. end;
  1054. if srsym.typ<>labelsym then
  1055. begin
  1056. Message(sym_e_id_is_no_label_id);
  1057. code:=cerrornode.create;
  1058. end
  1059. else
  1060. begin
  1061. { goto outside the current scope? }
  1062. if srsym.owner<>current_procinfo.procdef.localst then
  1063. begin
  1064. { allowed? }
  1065. if not(m_non_local_goto in current_settings.modeswitches) then
  1066. Message(parser_e_goto_outside_proc);
  1067. include(current_procinfo.flags,pi_has_global_goto);
  1068. end;
  1069. code:=cgotonode.create(tlabelsym(srsym));
  1070. tgotonode(code).labelsym:=tlabelsym(srsym);
  1071. { set flag that this label is used }
  1072. tlabelsym(srsym).used:=true;
  1073. end;
  1074. end;
  1075. end;
  1076. _BEGIN :
  1077. code:=statement_block(_BEGIN);
  1078. _IF :
  1079. code:=if_statement;
  1080. _CASE :
  1081. code:=case_statement;
  1082. _REPEAT :
  1083. code:=repeat_statement;
  1084. _WHILE :
  1085. code:=while_statement;
  1086. _FOR :
  1087. code:=for_statement;
  1088. _WITH :
  1089. code:=with_statement;
  1090. _TRY :
  1091. code:=try_statement;
  1092. _RAISE :
  1093. code:=raise_statement;
  1094. { semicolons,else until and end are ignored }
  1095. _SEMICOLON,
  1096. _ELSE,
  1097. _UNTIL,
  1098. _END:
  1099. code:=cnothingnode.create;
  1100. _FAIL :
  1101. begin
  1102. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1103. Message(parser_e_fail_only_in_constructor);
  1104. consume(_FAIL);
  1105. code:=cnodeutils.call_fail_node;
  1106. end;
  1107. _ASM :
  1108. begin
  1109. if parse_generic then
  1110. Message(parser_e_no_assembler_in_generic);
  1111. code:=_asm_statement;
  1112. end;
  1113. _EOF :
  1114. Message(scan_f_end_of_file);
  1115. else
  1116. begin
  1117. { don't typecheck yet, because that will also simplify, which may
  1118. result in not detecting certain kinds of syntax errors --
  1119. see mantis #15594 }
  1120. p:=expr(false);
  1121. { save the pattern here for latter usage, the label could be "000",
  1122. even if we read an expression, the pattern is still valid if it's really
  1123. a label (FK)
  1124. if you want to mess here, take care of
  1125. tests/webtbs/tw3546.pp
  1126. }
  1127. s:=pattern;
  1128. { When a colon follows a intconst then transform it into a label }
  1129. if (p.nodetype=ordconstn) and
  1130. try_to_consume(_COLON) then
  1131. begin
  1132. { in iso mode, 0003: is equal to 3: }
  1133. if m_iso in current_settings.modeswitches then
  1134. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1135. else
  1136. searchsym(s,srsym,srsymtable);
  1137. p.free;
  1138. if assigned(srsym) and
  1139. (srsym.typ=labelsym) then
  1140. begin
  1141. if tlabelsym(srsym).defined then
  1142. Message(sym_e_label_already_defined);
  1143. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1144. begin
  1145. tlabelsym(srsym).nonlocal:=true;
  1146. exclude(current_procinfo.procdef.procoptions,po_inline);
  1147. end;
  1148. if tlabelsym(srsym).nonlocal and
  1149. (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1150. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1151. tlabelsym(srsym).defined:=true;
  1152. p:=clabelnode.create(nil,tlabelsym(srsym));
  1153. tlabelsym(srsym).code:=p;
  1154. end
  1155. else
  1156. begin
  1157. Message1(sym_e_label_used_and_not_defined,s);
  1158. p:=cnothingnode.create;
  1159. end;
  1160. end;
  1161. if p.nodetype=labeln then
  1162. begin
  1163. { the pointer to the following instruction }
  1164. { isn't a very clean way }
  1165. if token in endtokens then
  1166. tlabelnode(p).left:=cnothingnode.create
  1167. else
  1168. tlabelnode(p).left:=statement();
  1169. { be sure to have left also typecheckpass }
  1170. typecheckpass(tlabelnode(p).left);
  1171. end
  1172. else
  1173. { change a load of a procvar to a call. this is also
  1174. supported in fpc mode }
  1175. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1176. maybe_call_procvar(p,false);
  1177. { blockn support because a read/write is changed into a blocknode
  1178. with a separate statement for each read/write operation (JM)
  1179. the same is true for val() if the third parameter is not 32 bit
  1180. goto nodes are created by the compiler for non local exit statements, so
  1181. include them as well
  1182. }
  1183. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1184. continuen,labeln,blockn,exitn,goton]) or
  1185. ((p.nodetype=inlinen) and
  1186. not is_void(p.resultdef)) or
  1187. ((p.nodetype=calln) and
  1188. (assigned(tcallnode(p).procdefinition)) and
  1189. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1190. Message(parser_e_illegal_expression);
  1191. if not assigned(p.resultdef) then
  1192. do_typecheckpass(p);
  1193. { Specify that we don't use the value returned by the call.
  1194. This is used for :
  1195. - dispose of temp stack space
  1196. - dispose on FPU stack
  1197. - extended syntax checking }
  1198. if (p.nodetype=calln) then
  1199. begin
  1200. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1201. { in $x- state, the function result must not be ignored }
  1202. if not(cs_extsyntax in current_settings.moduleswitches) and
  1203. not(is_void(p.resultdef)) and
  1204. { can be nil in case there was an error in the expression }
  1205. assigned(tcallnode(p).procdefinition) and
  1206. { allow constructor calls to drop the result if they are
  1207. called as instance methods instead of class methods }
  1208. not(
  1209. (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1210. is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
  1211. assigned(tcallnode(p).methodpointer) and
  1212. (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
  1213. ) then
  1214. Message(parser_e_illegal_expression);
  1215. end;
  1216. code:=p;
  1217. end;
  1218. end;
  1219. if assigned(code) then
  1220. begin
  1221. typecheckpass(code);
  1222. code.fileinfo:=filepos;
  1223. end;
  1224. statement:=code;
  1225. end;
  1226. function statement_block(starttoken : ttoken) : tnode;
  1227. var
  1228. first,last : tnode;
  1229. filepos : tfileposinfo;
  1230. begin
  1231. first:=nil;
  1232. last:=nil;
  1233. filepos:=current_tokenpos;
  1234. consume(starttoken);
  1235. while not(token in [_END,_FINALIZATION]) do
  1236. begin
  1237. if first=nil then
  1238. begin
  1239. last:=cstatementnode.create(statement,nil);
  1240. first:=last;
  1241. end
  1242. else
  1243. begin
  1244. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1245. last:=tstatementnode(last).right;
  1246. end;
  1247. if (token in [_END,_FINALIZATION]) then
  1248. break
  1249. else
  1250. begin
  1251. { if no semicolon, then error and go on }
  1252. if token<>_SEMICOLON then
  1253. begin
  1254. consume(_SEMICOLON);
  1255. consume_all_until(_SEMICOLON);
  1256. end;
  1257. consume(_SEMICOLON);
  1258. end;
  1259. consume_emptystats;
  1260. end;
  1261. { don't consume the finalization token, it is consumed when
  1262. reading the finalization block, but allow it only after
  1263. an initalization ! }
  1264. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1265. consume(_END);
  1266. last:=cblocknode.create(first);
  1267. last.fileinfo:=filepos;
  1268. statement_block:=last;
  1269. end;
  1270. function assembler_block : tnode;
  1271. var
  1272. p : tnode;
  1273. {$ifndef arm}
  1274. locals : longint;
  1275. {$endif arm}
  1276. srsym : tsym;
  1277. begin
  1278. if parse_generic then
  1279. message(parser_e_no_assembler_in_generic);
  1280. { Rename the funcret so that recursive calls are possible }
  1281. if not is_void(current_procinfo.procdef.returndef) then
  1282. begin
  1283. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1284. if assigned(srsym) then
  1285. srsym.realname:='$hiddenresult';
  1286. end;
  1287. { delphi uses register calling for assembler methods }
  1288. if (m_delphi in current_settings.modeswitches) and
  1289. (po_assembler in current_procinfo.procdef.procoptions) and
  1290. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1291. current_procinfo.procdef.proccalloption:=pocall_register;
  1292. { force the asm statement }
  1293. if token<>_ASM then
  1294. consume(_ASM);
  1295. include(current_procinfo.flags,pi_is_assembler);
  1296. p:=_asm_statement;
  1297. {$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1298. if (po_assembler in current_procinfo.procdef.procoptions) then
  1299. begin
  1300. { set the framepointer to esp for assembler functions when the
  1301. following conditions are met:
  1302. - if the are no local variables and parameters (except the allocated result)
  1303. - no reference to the result variable (refcount<=1)
  1304. - result is not stored as parameter
  1305. - target processor has optional frame pointer save
  1306. (vm, i386, vm only currently)
  1307. }
  1308. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1309. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1310. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1311. if (locals=0) and
  1312. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1313. (not assigned(current_procinfo.procdef.funcretsym) or
  1314. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1315. not (df_generic in current_procinfo.procdef.defoptions) and
  1316. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1317. begin
  1318. { Only need to set the framepointer, the locals will
  1319. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1320. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1321. end;
  1322. end;
  1323. {$endif not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) not(defined(mipsel))}
  1324. { Flag the result as assigned when it is returned in a
  1325. register.
  1326. }
  1327. if assigned(current_procinfo.procdef.funcretsym) and
  1328. not (df_generic in current_procinfo.procdef.defoptions) and
  1329. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1330. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1331. { because the END is already read we need to get the
  1332. last_endtoken_filepos here (PFV) }
  1333. last_endtoken_filepos:=current_tokenpos;
  1334. assembler_block:=p;
  1335. end;
  1336. end.