pstatmnt.pas 48 KB

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