pdecvar.pas 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Parses variable declarations. Used for var statement and record
  4. definitions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pdecvar;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. symsym,symdef;
  23. type
  24. tvar_dec_option=(vd_record,vd_object,vd_threadvar);
  25. tvar_dec_options=set of tvar_dec_option;
  26. function read_property_dec(aclass:tobjectdef):tpropertysym;
  27. procedure read_var_decls(options:Tvar_dec_options);
  28. procedure read_record_fields(options:Tvar_dec_options);
  29. implementation
  30. uses
  31. SysUtils,
  32. { common }
  33. cutils,cclasses,
  34. { global }
  35. globtype,globals,tokens,verbose,
  36. systems,
  37. { symtable }
  38. symconst,symbase,symtype,symtable,defutil,defcmp,
  39. fmodule,
  40. { pass 1 }
  41. node,pass_1,aasmdata,
  42. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nmem,
  43. { codegen }
  44. ncgutil,
  45. { parser }
  46. scanner,
  47. pbase,pexpr,ptype,ptconst,pdecsub,
  48. { link }
  49. import
  50. ;
  51. function read_property_dec(aclass:tobjectdef):tpropertysym;
  52. { convert a node tree to symlist and return the last
  53. symbol }
  54. function parse_symlist(pl:tpropaccesslist;var def:tdef):boolean;
  55. var
  56. idx : longint;
  57. sym : tsym;
  58. srsymtable : tsymtable;
  59. st : tsymtable;
  60. p : tnode;
  61. begin
  62. result:=true;
  63. def:=nil;
  64. if token=_ID then
  65. begin
  66. if assigned(aclass) then
  67. sym:=search_class_member(aclass,pattern)
  68. else
  69. searchsym(pattern,sym,srsymtable);
  70. if assigned(sym) then
  71. begin
  72. case sym.typ of
  73. fieldvarsym :
  74. begin
  75. if not(sp_private in current_object_option) then
  76. addsymref(sym);
  77. pl.addsym(sl_load,sym);
  78. def:=tfieldvarsym(sym).vardef;
  79. end;
  80. procsym :
  81. begin
  82. if not(sp_private in current_object_option) then
  83. addsymref(sym);
  84. pl.addsym(sl_call,sym);
  85. end;
  86. else
  87. begin
  88. Message1(parser_e_illegal_field_or_method,orgpattern);
  89. result:=false;
  90. end;
  91. end;
  92. end
  93. else
  94. begin
  95. Message1(parser_e_illegal_field_or_method,orgpattern);
  96. result:=false;
  97. end;
  98. consume(_ID);
  99. repeat
  100. case token of
  101. _ID,
  102. _SEMICOLON :
  103. begin
  104. break;
  105. end;
  106. _POINT :
  107. begin
  108. consume(_POINT);
  109. if assigned(def) then
  110. begin
  111. st:=def.getsymtable(gs_record);
  112. if assigned(st) then
  113. begin
  114. sym:=tsym(st.search(pattern));
  115. if assigned(sym) then
  116. begin
  117. pl.addsym(sl_subscript,sym);
  118. case sym.typ of
  119. fieldvarsym :
  120. def:=tfieldvarsym(sym).vardef;
  121. else
  122. begin
  123. Message1(sym_e_illegal_field,orgpattern);
  124. result:=false;
  125. end;
  126. end;
  127. end
  128. else
  129. begin
  130. Message1(sym_e_illegal_field,orgpattern);
  131. result:=false;
  132. end;
  133. end
  134. else
  135. begin
  136. Message(parser_e_invalid_qualifier);
  137. result:=false;
  138. end;
  139. end
  140. else
  141. begin
  142. Message(parser_e_invalid_qualifier);
  143. result:=false;
  144. end;
  145. consume(_ID);
  146. end;
  147. _LECKKLAMMER :
  148. begin
  149. consume(_LECKKLAMMER);
  150. repeat
  151. if def.deftype=arraydef then
  152. begin
  153. idx:=0;
  154. p:=comp_expr(true);
  155. if (not codegenerror) then
  156. begin
  157. if (p.nodetype=ordconstn) then
  158. begin
  159. if compare_defs(p.resultdef,tarraydef(def).rangedef,nothingn)>=te_equal then
  160. idx:=tordconstnode(p).value
  161. else
  162. IncompatibleTypes(p.resultdef,tarraydef(def).rangedef);
  163. end
  164. else
  165. Message(type_e_ordinal_expr_expected)
  166. end;
  167. p.free;
  168. pl.addconst(sl_vec,idx,p.resultdef);
  169. def:=tarraydef(def).elementdef;
  170. end
  171. else
  172. begin
  173. Message(parser_e_invalid_qualifier);
  174. result:=false;
  175. end;
  176. until not try_to_consume(_COMMA);
  177. consume(_RECKKLAMMER);
  178. end;
  179. else
  180. begin
  181. Message(parser_e_ill_property_access_sym);
  182. result:=false;
  183. break;
  184. end;
  185. end;
  186. until false;
  187. end
  188. else
  189. begin
  190. Message(parser_e_ill_property_access_sym);
  191. result:=false;
  192. end;
  193. end;
  194. var
  195. sym : tsym;
  196. p : tpropertysym;
  197. overriden : tsym;
  198. varspez : tvarspez;
  199. hdef : tdef;
  200. arraytype : tdef;
  201. def : tdef;
  202. pt : tnode;
  203. sc : TFPObjectList;
  204. paranr : word;
  205. i : longint;
  206. intfidx: longint;
  207. hreadparavs,
  208. hparavs : tparavarsym;
  209. storedprocdef,
  210. readprocdef,
  211. writeprocdef : tprocvardef;
  212. begin
  213. { Generate temp procvardefs to search for matching read/write
  214. procedures. the readprocdef will store all definitions }
  215. paranr:=0;
  216. readprocdef:=tprocvardef.create(normal_function_level);
  217. writeprocdef:=tprocvardef.create(normal_function_level);
  218. storedprocdef:=tprocvardef.create(normal_function_level);
  219. { make it method pointers }
  220. if assigned(aclass) then
  221. begin
  222. include(readprocdef.procoptions,po_methodpointer);
  223. include(writeprocdef.procoptions,po_methodpointer);
  224. include(storedprocdef.procoptions,po_methodpointer);
  225. end;
  226. { method for stored must return boolean }
  227. storedprocdef.returndef:=booltype;
  228. if token<>_ID then
  229. begin
  230. consume(_ID);
  231. consume(_SEMICOLON);
  232. exit;
  233. end;
  234. { Generate propertysym and insert in symtablestack }
  235. p:=tpropertysym.create(orgpattern);
  236. symtablestack.top.insert(p);
  237. consume(_ID);
  238. { property parameters ? }
  239. if try_to_consume(_LECKKLAMMER) then
  240. begin
  241. if (sp_published in current_object_option) and
  242. not (m_delphi in current_settings.modeswitches) then
  243. Message(parser_e_cant_publish_that_property);
  244. { create a list of the parameters }
  245. symtablestack.push(readprocdef.parast);
  246. sc:=TFPObjectList.create(false);
  247. inc(testcurobject);
  248. repeat
  249. if try_to_consume(_VAR) then
  250. varspez:=vs_var
  251. else if try_to_consume(_CONST) then
  252. varspez:=vs_const
  253. else if (m_out in current_settings.modeswitches) and try_to_consume(_OUT) then
  254. varspez:=vs_out
  255. else
  256. varspez:=vs_value;
  257. sc.clear;
  258. repeat
  259. inc(paranr);
  260. hreadparavs:=tparavarsym.create(orgpattern,10*paranr,varspez,generrordef,[]);
  261. readprocdef.parast.insert(hreadparavs);
  262. sc.add(hreadparavs);
  263. consume(_ID);
  264. until not try_to_consume(_COMMA);
  265. if try_to_consume(_COLON) then
  266. begin
  267. if try_to_consume(_ARRAY) then
  268. begin
  269. consume(_OF);
  270. { define range and type of range }
  271. hdef:=tarraydef.create(0,-1,s32inttype);
  272. { define field type }
  273. single_type(arraytype,false);
  274. tarraydef(hdef).elementdef:=arraytype;
  275. end
  276. else
  277. single_type(hdef,false);
  278. end
  279. else
  280. hdef:=cformaltype;
  281. for i:=0 to sc.count-1 do
  282. begin
  283. hreadparavs:=tparavarsym(sc[i]);
  284. hreadparavs.vardef:=hdef;
  285. { also update the writeprocdef }
  286. hparavs:=tparavarsym.create(hreadparavs.realname,hreadparavs.paranr,vs_value,hdef,[]);
  287. writeprocdef.parast.insert(hparavs);
  288. end;
  289. until not try_to_consume(_SEMICOLON);
  290. sc.free;
  291. dec(testcurobject);
  292. symtablestack.pop(readprocdef.parast);
  293. consume(_RECKKLAMMER);
  294. { the parser need to know if a property has parameters, the
  295. index parameter doesn't count (PFV) }
  296. if paranr>0 then
  297. include(p.propoptions,ppo_hasparameters);
  298. end;
  299. { overriden property ? }
  300. { force property interface
  301. there is a property parameter
  302. a global property }
  303. if (token=_COLON) or (paranr>0) or (aclass=nil) then
  304. begin
  305. consume(_COLON);
  306. single_type(p.propdef,false);
  307. if (idtoken=_INDEX) then
  308. begin
  309. consume(_INDEX);
  310. pt:=comp_expr(true);
  311. { Only allow enum and integer indexes. Convert all integer
  312. values to s32int to be compatible with delphi, because the
  313. procedure matching requires equal parameters }
  314. if is_constnode(pt) and
  315. is_ordinal(pt.resultdef)
  316. {$ifndef cpu64bit}
  317. and (not is_64bitint(pt.resultdef))
  318. {$endif cpu64bit}
  319. then
  320. begin
  321. if is_integer(pt.resultdef) then
  322. inserttypeconv_internal(pt,s32inttype);
  323. p.index:=tordconstnode(pt).value;
  324. end
  325. else
  326. begin
  327. Message(parser_e_invalid_property_index_value);
  328. p.index:=0;
  329. end;
  330. p.indexdef:=pt.resultdef;
  331. include(p.propoptions,ppo_indexed);
  332. { concat a longint to the para templates }
  333. inc(paranr);
  334. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  335. readprocdef.parast.insert(hparavs);
  336. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  337. writeprocdef.parast.insert(hparavs);
  338. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  339. storedprocdef.parast.insert(hparavs);
  340. pt.free;
  341. end;
  342. end
  343. else
  344. begin
  345. { do an property override }
  346. overriden:=search_class_member(aclass.childof,p.name);
  347. if assigned(overriden) and
  348. (overriden.typ=propertysym) and
  349. not(is_dispinterface(aclass)) then
  350. begin
  351. p.overridenpropsym:=tpropertysym(overriden);
  352. { inherit all type related entries }
  353. p.indexdef:=tpropertysym(overriden).indexdef;
  354. p.propdef:=tpropertysym(overriden).propdef;
  355. p.index:=tpropertysym(overriden).index;
  356. p.default:=tpropertysym(overriden).default;
  357. p.propoptions:=tpropertysym(overriden).propoptions;
  358. end
  359. else
  360. begin
  361. p.propdef:=generrordef;
  362. message(parser_e_no_property_found_to_override);
  363. end;
  364. end;
  365. if ((sp_published in current_object_option) or is_dispinterface(aclass)) and
  366. not(p.propdef.is_publishable) then
  367. Message(parser_e_cant_publish_that_property);
  368. if not(is_dispinterface(aclass)) then
  369. begin
  370. if try_to_consume(_READ) then
  371. begin
  372. p.propaccesslist[palt_read].clear;
  373. if parse_symlist(p.propaccesslist[palt_read],def) then
  374. begin
  375. sym:=p.propaccesslist[palt_read].firstsym^.sym;
  376. case sym.typ of
  377. procsym :
  378. begin
  379. { read is function returning the type of the property }
  380. readprocdef.returndef:=p.propdef;
  381. { Insert hidden parameters }
  382. handle_calling_convention(readprocdef);
  383. { search procdefs matching readprocdef }
  384. { we ignore hidden stuff here because the property access symbol might have
  385. non default calling conventions which might change the hidden stuff;
  386. see tw3216.pp (FK) }
  387. p.propaccesslist[palt_read].procdef:=Tprocsym(sym).search_procdef_bypara(readprocdef.paras,p.propdef,[cpo_allowdefaults,cpo_ignorehidden]);
  388. if not assigned(p.propaccesslist[palt_read].procdef) then
  389. Message(parser_e_ill_property_access_sym);
  390. end;
  391. fieldvarsym :
  392. begin
  393. if not assigned(def) then
  394. internalerror(200310071);
  395. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  396. begin
  397. { property parameters are allowed if this is
  398. an indexed property, because the index is then
  399. the parameter.
  400. Note: In the help of Kylix it is written
  401. that it isn't allowed, but the compiler accepts it (PFV) }
  402. if (ppo_hasparameters in p.propoptions) then
  403. Message(parser_e_ill_property_access_sym);
  404. end
  405. else
  406. IncompatibleTypes(def,p.propdef);
  407. end;
  408. else
  409. Message(parser_e_ill_property_access_sym);
  410. end;
  411. end;
  412. end;
  413. if try_to_consume(_WRITE) then
  414. begin
  415. p.propaccesslist[palt_write].clear;
  416. if parse_symlist(p.propaccesslist[palt_write],def) then
  417. begin
  418. sym:=p.propaccesslist[palt_write].firstsym^.sym;
  419. case sym.typ of
  420. procsym :
  421. begin
  422. { write is a procedure with an extra value parameter
  423. of the of the property }
  424. writeprocdef.returndef:=voidtype;
  425. inc(paranr);
  426. hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  427. writeprocdef.parast.insert(hparavs);
  428. { Insert hidden parameters }
  429. handle_calling_convention(writeprocdef);
  430. { search procdefs matching writeprocdef }
  431. p.propaccesslist[palt_write].procdef:=Tprocsym(sym).search_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults]);
  432. if not assigned(p.propaccesslist[palt_write].procdef) then
  433. Message(parser_e_ill_property_access_sym);
  434. end;
  435. fieldvarsym :
  436. begin
  437. if not assigned(def) then
  438. internalerror(200310072);
  439. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  440. begin
  441. { property parameters are allowed if this is
  442. an indexed property, because the index is then
  443. the parameter.
  444. Note: In the help of Kylix it is written
  445. that it isn't allowed, but the compiler accepts it (PFV) }
  446. if (ppo_hasparameters in p.propoptions) then
  447. Message(parser_e_ill_property_access_sym);
  448. end
  449. else
  450. IncompatibleTypes(def,p.propdef);
  451. end;
  452. else
  453. Message(parser_e_ill_property_access_sym);
  454. end;
  455. end;
  456. end;
  457. end
  458. else
  459. begin
  460. if try_to_consume(_READONLY) then
  461. begin
  462. end
  463. else if try_to_consume(_WRITEONLY) then
  464. begin
  465. end;
  466. if try_to_consume(_DISPID) then
  467. begin
  468. pt:=comp_expr(true);
  469. if is_constintnode(pt) then
  470. // tprocdef(pd).extnumber:=tordconstnode(pt).value
  471. else
  472. Message(parser_e_dispid_must_be_ord_const);
  473. pt.free;
  474. end;
  475. end;
  476. if assigned(aclass) and not(is_dispinterface(aclass)) then
  477. begin
  478. { ppo_stored is default on for not overriden properties }
  479. if not assigned(p.overridenpropsym) then
  480. include(p.propoptions,ppo_stored);
  481. if try_to_consume(_STORED) then
  482. begin
  483. include(p.propoptions,ppo_stored);
  484. p.propaccesslist[palt_stored].clear;
  485. case token of
  486. _ID:
  487. begin
  488. { in the case that idtoken=_DEFAULT }
  489. { we have to do nothing except }
  490. { setting ppo_stored, it's the same }
  491. { as stored true }
  492. if idtoken<>_DEFAULT then
  493. begin
  494. if parse_symlist(p.propaccesslist[palt_stored],def) then
  495. begin
  496. sym:=p.propaccesslist[palt_stored].firstsym^.sym;
  497. case sym.typ of
  498. procsym :
  499. begin
  500. { Insert hidden parameters }
  501. handle_calling_convention(storedprocdef);
  502. p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).search_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
  503. if not assigned(p.propaccesslist[palt_stored].procdef) then
  504. message(parser_e_ill_property_storage_sym);
  505. end;
  506. fieldvarsym :
  507. begin
  508. if not assigned(def) then
  509. internalerror(200310073);
  510. if (ppo_hasparameters in p.propoptions) or
  511. not(is_boolean(def)) then
  512. Message(parser_e_stored_property_must_be_boolean);
  513. end;
  514. else
  515. Message(parser_e_ill_property_access_sym);
  516. end;
  517. end;
  518. end;
  519. end;
  520. _FALSE:
  521. begin
  522. consume(_FALSE);
  523. exclude(p.propoptions,ppo_stored);
  524. end;
  525. _TRUE:
  526. begin
  527. p.default:=longint($80000000);
  528. consume(_TRUE);
  529. end;
  530. end;
  531. end;
  532. end;
  533. if try_to_consume(_DEFAULT) then
  534. begin
  535. if not(is_ordinal(p.propdef) or
  536. {$ifndef cpu64bit}
  537. is_64bitint(p.propdef) or
  538. {$endif cpu64bit}
  539. is_class(p.propdef) or
  540. is_single(p.propdef) or
  541. (p.propdef.deftype in [classrefdef,pointerdef]) or
  542. ((p.propdef.deftype=setdef) and
  543. (tsetdef(p.propdef).settype=smallset))) or
  544. ((p.propdef.deftype=arraydef) and
  545. (ppo_indexed in p.propoptions)) or
  546. (ppo_hasparameters in p.propoptions) then
  547. begin
  548. Message(parser_e_property_cant_have_a_default_value);
  549. { Error recovery }
  550. pt:=comp_expr(true);
  551. pt.free;
  552. end
  553. else
  554. begin
  555. { Get the result of the default, the firstpass is
  556. needed to support values like -1 }
  557. pt:=comp_expr(true);
  558. if (p.propdef.deftype=setdef) and
  559. (pt.nodetype=arrayconstructorn) then
  560. begin
  561. arrayconstructor_to_set(pt);
  562. do_typecheckpass(pt);
  563. end;
  564. inserttypeconv(pt,p.propdef);
  565. if not(is_constnode(pt)) then
  566. Message(parser_e_property_default_value_must_const);
  567. { Set default value }
  568. case pt.nodetype of
  569. setconstn :
  570. p.default:=plongint(tsetconstnode(pt).value_set)^;
  571. ordconstn :
  572. p.default:=longint(tordconstnode(pt).value);
  573. niln :
  574. p.default:=0;
  575. realconstn:
  576. p.default:=longint(single(trealconstnode(pt).value_real));
  577. end;
  578. pt.free;
  579. end;
  580. end
  581. else if try_to_consume(_NODEFAULT) then
  582. begin
  583. p.default:=longint($80000000);
  584. end;
  585. { Parse possible "implements" keyword }
  586. if try_to_consume(_IMPLEMENTS) then
  587. begin
  588. consume(_ID);
  589. {$message warn unlocalized string}
  590. if not is_interface(p.propdef) then
  591. begin
  592. writeln('Implements property must have interface type');
  593. Message1(sym_e_illegal_field, pattern);
  594. end;
  595. if pattern <> p.propdef.mangledparaname() then
  596. begin
  597. writeln('Implements-property must implement interface of correct type');
  598. Message1(sym_e_illegal_field, pattern);
  599. end;
  600. intfidx := 0;
  601. with aclass.implementedinterfaces do
  602. begin
  603. for i := 1 to count do
  604. if interfaces(i).objname^ = pattern then
  605. begin
  606. intfidx := i;
  607. break;
  608. end;
  609. if intfidx > 0 then
  610. begin
  611. interfaces(intfidx).iitype := etFieldValue;
  612. interfaces(intfidx).iioffset := tfieldvarsym(p.propaccesslist[palt_read].firstsym^.sym).fieldoffset;
  613. end else
  614. begin
  615. writeln('Implements-property used on unimplemented interface');
  616. Message1(sym_e_illegal_field, pattern);
  617. end;
  618. end;
  619. end;
  620. { remove temporary procvardefs }
  621. readprocdef.free;
  622. writeprocdef.free;
  623. result:=p;
  624. end;
  625. function maybe_parse_proc_directives(def:tdef):boolean;
  626. var
  627. newtype : ttypesym;
  628. begin
  629. result:=false;
  630. { Process procvar directives before = and ; }
  631. if (def.deftype=procvardef) and
  632. (def.typesym=nil) and
  633. check_proc_directive(true) then
  634. begin
  635. newtype:=ttypesym.create('unnamed',def);
  636. parse_var_proc_directives(tsym(newtype));
  637. newtype.typedef:=nil;
  638. def.typesym:=nil;
  639. newtype.free;
  640. result:=true;
  641. end;
  642. end;
  643. const
  644. variantrecordlevel : longint = 0;
  645. procedure read_var_decls(options:Tvar_dec_options);
  646. procedure read_default_value(sc : TFPObjectList;def:tdef;is_threadvar : boolean);
  647. var
  648. vs : tabstractnormalvarsym;
  649. tcsym : ttypedconstsym;
  650. begin
  651. vs:=tabstractnormalvarsym(sc[0]);
  652. if sc.count>1 then
  653. Message(parser_e_initialized_only_one_var);
  654. if is_threadvar then
  655. Message(parser_e_initialized_not_for_threadvar);
  656. if symtablestack.top.symtabletype=localsymtable then
  657. begin
  658. consume(_EQUAL);
  659. tcsym:=ttypedconstsym.create('$default'+vs.realname,def,false);
  660. include(tcsym.symoptions,sp_internal);
  661. vs.defaultconstsym:=tcsym;
  662. symtablestack.top.insert(tcsym);
  663. readtypedconst(current_asmdata.asmlists[al_typedconsts],def,tcsym,false);
  664. { The variable has a value assigned }
  665. vs.varstate:=vs_initialised;
  666. end
  667. else
  668. begin
  669. tcsym:=ttypedconstsym.create(vs.realname,def,true);
  670. tcsym.fileinfo:=vs.fileinfo;
  671. symtablestack.top.replace(vs,tcsym);
  672. vs.free;
  673. consume(_EQUAL);
  674. readtypedconst(current_asmdata.asmlists[al_typedconsts],def,tcsym,true);
  675. end;
  676. end;
  677. var
  678. sc : TFPObjectList;
  679. i : longint;
  680. old_block_type : tblock_type;
  681. symdone : boolean;
  682. { to handle absolute }
  683. abssym : tabsolutevarsym;
  684. { c var }
  685. is_dll,
  686. hasdefaultvalue,
  687. is_gpc_name,is_cdecl,
  688. extern_var,export_var : boolean;
  689. old_current_object_option : tsymoptions;
  690. hs,sorg,C_name,dll_name : string;
  691. hdef : tdef;
  692. hp,pt : tnode;
  693. vs : tabstractvarsym;
  694. hintsymoptions : tsymoptions;
  695. semicolonatend,semicoloneaten: boolean;
  696. begin
  697. old_current_object_option:=current_object_option;
  698. { all variables are public if not in a object declaration }
  699. current_object_option:=[sp_public];
  700. old_block_type:=block_type;
  701. block_type:=bt_type;
  702. is_gpc_name:=false;
  703. { Force an expected ID error message }
  704. if not (token in [_ID,_CASE,_END]) then
  705. consume(_ID);
  706. { read vars }
  707. sc:=TFPObjectList.create(false);
  708. while (token=_ID) do
  709. begin
  710. sorg:=orgpattern;
  711. semicoloneaten:=false;
  712. hasdefaultvalue:=false;
  713. symdone:=false;
  714. sc.clear;
  715. repeat
  716. if (token = _ID) then
  717. begin
  718. case symtablestack.top.symtabletype of
  719. localsymtable :
  720. vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  721. staticsymtable,
  722. globalsymtable :
  723. vs:=tglobalvarsym.create(orgpattern,vs_value,generrordef,[]);
  724. else
  725. internalerror(200411064);
  726. end;
  727. sc.add(vs);
  728. symtablestack.top.insert(vs);
  729. end;
  730. consume(_ID);
  731. until not try_to_consume(_COMMA);
  732. consume(_COLON);
  733. if (m_gpc in current_settings.modeswitches) and
  734. (token=_ID) and
  735. (orgpattern='__asmname__') then
  736. begin
  737. consume(_ID);
  738. C_name:=get_stringconst;
  739. Is_gpc_name:=true;
  740. end;
  741. { this is needed for Delphi mode at least
  742. but should be OK for all modes !! (PM) }
  743. ignore_equal:=true;
  744. read_anon_type(hdef,false);
  745. ignore_equal:=false;
  746. { Process procvar directives }
  747. if maybe_parse_proc_directives(hdef) then
  748. semicoloneaten:=true;
  749. if is_gpc_name then
  750. begin
  751. vs:=tabstractvarsym(sc[0]);
  752. if sc.count>1 then
  753. Message(parser_e_absolute_only_one_var);
  754. vs.vardef:=hdef;
  755. if vs.typ=globalvarsym then
  756. begin
  757. tglobalvarsym(vs).set_mangledname(target_info.Cprefix+sorg);
  758. include(vs.varoptions,vo_is_C_var);
  759. include(vs.varoptions,vo_is_external);
  760. end
  761. else
  762. Message(parser_e_no_local_var_external);
  763. symdone:=true;
  764. end;
  765. { check for absolute }
  766. if not symdone and
  767. try_to_consume(_ABSOLUTE) then
  768. begin
  769. abssym:=nil;
  770. { only allowed for one var }
  771. vs:=tabstractvarsym(sc[0]);
  772. if sc.count>1 then
  773. Message(parser_e_absolute_only_one_var);
  774. { parse the rest }
  775. pt:=expr;
  776. { check allowed absolute types }
  777. if (pt.nodetype=stringconstn) or
  778. (is_constcharnode(pt)) then
  779. begin
  780. abssym:=tabsolutevarsym.create(vs.realname,hdef);
  781. abssym.fileinfo:=vs.fileinfo;
  782. if pt.nodetype=stringconstn then
  783. hs:=strpas(tstringconstnode(pt).value_str)
  784. else
  785. hs:=chr(tordconstnode(pt).value);
  786. consume(token);
  787. abssym.abstyp:=toasm;
  788. abssym.asmname:=stringdup(hs);
  789. { replace the varsym }
  790. symtablestack.top.replace(vs,abssym);
  791. vs.free;
  792. end
  793. { address }
  794. else if is_constintnode(pt) and
  795. ((target_info.system in [system_i386_go32v2,system_i386_watcom,
  796. system_i386_wdosx,system_i386_win32,
  797. system_arm_wince,system_i386_wince,
  798. system_arm_gba]) or
  799. (m_objfpc in current_settings.modeswitches) or
  800. (m_delphi in current_settings.modeswitches)) then
  801. begin
  802. abssym:=tabsolutevarsym.create(vs.realname,hdef);
  803. abssym.fileinfo:=vs.fileinfo;
  804. abssym.abstyp:=toaddr;
  805. abssym.addroffset:=tordconstnode(pt).value;
  806. {$ifdef i386}
  807. abssym.absseg:=false;
  808. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  809. try_to_consume(_COLON) then
  810. begin
  811. pt.free;
  812. pt:=expr;
  813. if is_constintnode(pt) then
  814. begin
  815. abssym.addroffset:=abssym.addroffset shl 4+tordconstnode(pt).value;
  816. abssym.absseg:=true;
  817. end
  818. else
  819. Message(type_e_ordinal_expr_expected);
  820. end;
  821. {$endif i386}
  822. symtablestack.top.replace(vs,abssym);
  823. vs.free;
  824. end
  825. { variable }
  826. else
  827. begin
  828. { remove subscriptn before checking for loadn }
  829. hp:=pt;
  830. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  831. hp:=tunarynode(hp).left;
  832. if (hp.nodetype=loadn) then
  833. begin
  834. { we should check the result type of loadn }
  835. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,globalvarsym,localvarsym,
  836. paravarsym,typedconstsym]) then
  837. Message(parser_e_absolute_only_to_var_or_const);
  838. abssym:=tabsolutevarsym.create(vs.realname,hdef);
  839. abssym.fileinfo:=vs.fileinfo;
  840. abssym.abstyp:=tovar;
  841. abssym.ref:=node_to_propaccesslist(pt);
  842. symtablestack.top.replace(vs,abssym);
  843. vs.free;
  844. end
  845. else
  846. Message(parser_e_absolute_only_to_var_or_const);
  847. end;
  848. if assigned(abssym) then
  849. begin
  850. { try to consume the hint directives with absolute symbols }
  851. hintsymoptions:=[];
  852. try_consume_hintdirective(hintsymoptions);
  853. abssym.symoptions := abssym.symoptions + hintsymoptions;
  854. end;
  855. pt.free;
  856. symdone:=true;
  857. end;
  858. { try to parse the hint directives }
  859. hintsymoptions:=[];
  860. try_consume_hintdirective(hintsymoptions);
  861. { Handling of Delphi typed const = initialized vars }
  862. if (token=_EQUAL) and
  863. not(m_tp7 in current_settings.modeswitches) and
  864. (symtablestack.top.symtabletype<>parasymtable) then
  865. begin
  866. { Add calling convention for procvar }
  867. if (hdef.deftype=procvardef) and
  868. (hdef.typesym=nil) then
  869. handle_calling_convention(tprocvardef(hdef));
  870. read_default_value(sc,hdef,vd_threadvar in options);
  871. consume(_SEMICOLON);
  872. { for locals we've created typedconstsym with a different name }
  873. if symtablestack.top.symtabletype<>localsymtable then
  874. symdone:=true;
  875. hasdefaultvalue:=true;
  876. end
  877. else
  878. begin
  879. if not(semicoloneaten) then
  880. consume(_SEMICOLON);
  881. end;
  882. { Support calling convention for procvars after semicolon }
  883. if not(hasdefaultvalue) and
  884. (hdef.deftype=procvardef) and
  885. (hdef.typesym=nil) then
  886. begin
  887. { Parse procvar directives after ; }
  888. maybe_parse_proc_directives(hdef);
  889. { Add calling convention for procvar }
  890. handle_calling_convention(tprocvardef(hdef));
  891. { Handling of Delphi typed const = initialized vars }
  892. if (token=_EQUAL) and
  893. not(m_tp7 in current_settings.modeswitches) and
  894. (symtablestack.top.symtabletype<>parasymtable) then
  895. begin
  896. read_default_value(sc,hdef,vd_threadvar in options);
  897. consume(_SEMICOLON);
  898. symdone:=true;
  899. hasdefaultvalue:=true;
  900. end;
  901. end;
  902. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  903. if not symdone then
  904. begin
  905. if (
  906. (token=_ID) and
  907. (m_cvar_support in current_settings.modeswitches) and
  908. (idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR])
  909. ) or
  910. (
  911. (m_mac in current_settings.modeswitches) and
  912. ((cs_external_var in current_settings.localswitches) or (cs_externally_visible in current_settings.localswitches))
  913. ) then
  914. begin
  915. { only allowed for one var }
  916. vs:=tabstractvarsym(sc[0]);
  917. if sc.count>1 then
  918. Message(parser_e_absolute_only_one_var);
  919. { set type of the var }
  920. vs.vardef:=hdef;
  921. vs.symoptions := vs.symoptions + hintsymoptions;
  922. { defaults }
  923. is_dll:=false;
  924. is_cdecl:=false;
  925. extern_var:=false;
  926. export_var:=false;
  927. C_name:=sorg;
  928. semicolonatend:= false;
  929. { cdecl }
  930. if try_to_consume(_CVAR) then
  931. begin
  932. consume(_SEMICOLON);
  933. is_cdecl:=true;
  934. C_name:=target_info.Cprefix+sorg;
  935. end;
  936. { external }
  937. if try_to_consume(_EXTERNAL) then
  938. begin
  939. extern_var:=true;
  940. semicolonatend:= true;
  941. end;
  942. { macpas specific handling due to some switches}
  943. if (m_mac in current_settings.modeswitches) then
  944. begin
  945. if (cs_external_var in current_settings.localswitches) then
  946. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  947. is_cdecl:=true;
  948. C_name:=target_info.Cprefix+sorg;
  949. extern_var:=true;
  950. end
  951. else if (cs_externally_visible in current_settings.localswitches) then
  952. begin {The effect of this is the same as if cvar has been given as directives.}
  953. is_cdecl:=true;
  954. C_name:=target_info.Cprefix+sorg;
  955. end;
  956. vs.varregable := vr_none;
  957. end;
  958. { export }
  959. if idtoken in [_EXPORT,_PUBLIC] then
  960. begin
  961. consume(_ID);
  962. if extern_var then
  963. Message(parser_e_not_external_and_export)
  964. else
  965. begin
  966. export_var:=true;
  967. semicolonatend:= true;
  968. end;
  969. end;
  970. { external and export need a name after when no cdecl is used }
  971. if not is_cdecl then
  972. begin
  973. { dll name ? }
  974. if (extern_var) and (idtoken<>_NAME) then
  975. begin
  976. is_dll:=true;
  977. dll_name:=ChangeFileExt(get_stringconst,target_info.sharedlibext);
  978. end;
  979. if try_to_consume(_NAME) then
  980. C_name:=get_stringconst
  981. else
  982. C_name:=sorg;
  983. end;
  984. { consume the ; when export or external is used }
  985. if semicolonatend then
  986. consume(_SEMICOLON);
  987. { set some vars options }
  988. if is_dll then
  989. begin
  990. { Windows uses an indirect reference using import tables }
  991. if target_info.system in system_all_windows then
  992. include(vs.varoptions,vo_is_dll_var);
  993. end
  994. else
  995. include(vs.varoptions,vo_is_C_var);
  996. if (is_dll) and
  997. (target_info.system in [system_powerpc_darwin,system_i386_darwin]) then
  998. C_Name := target_info.Cprefix+C_Name;
  999. if export_var then
  1000. begin
  1001. inc(vs.refs);
  1002. include(vs.varoptions,vo_is_exported);
  1003. end;
  1004. if extern_var then
  1005. include(vs.varoptions,vo_is_external);
  1006. if vs.typ=globalvarsym then
  1007. begin
  1008. tglobalvarsym(vs).set_mangledname(C_Name);
  1009. { insert in the al_globals when it is not external }
  1010. if (not extern_var) then
  1011. insertbssdata(tglobalvarsym(vs));
  1012. { now we can insert it in the import lib if its a dll, or
  1013. add it to the externals }
  1014. if extern_var then
  1015. begin
  1016. vs.varregable := vr_none;
  1017. if is_dll then
  1018. current_module.AddExternalImport(dll_name,C_Name,0,true)
  1019. else
  1020. if tf_has_dllscanner in target_info.flags then
  1021. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  1022. end;
  1023. end
  1024. else
  1025. Message(parser_e_no_local_var_external);
  1026. symdone:=true;
  1027. end;
  1028. end;
  1029. { insert it in the symtable, if not done yet }
  1030. if not symdone then
  1031. begin
  1032. for i:=0 to sc.count-1 do
  1033. begin
  1034. vs:=tabstractvarsym(sc[i]);
  1035. vs.vardef:=hdef;
  1036. { insert any additional hint directives }
  1037. vs.symoptions := vs.symoptions + hintsymoptions;
  1038. if vd_threadvar in options then
  1039. include(vs.varoptions,vo_is_thread_var);
  1040. { static data fields are inserted in the globalsymtable }
  1041. if vs.typ=globalvarsym then
  1042. insertbssdata(tglobalvarsym(vs));
  1043. end;
  1044. end;
  1045. end;
  1046. block_type:=old_block_type;
  1047. current_object_option:=old_current_object_option;
  1048. { free the list }
  1049. sc.free;
  1050. end;
  1051. procedure read_record_fields(options:Tvar_dec_options);
  1052. var
  1053. sc : TFPObjectList;
  1054. i : longint;
  1055. old_block_type : tblock_type;
  1056. old_current_object_option : tsymoptions;
  1057. hs,sorg : string;
  1058. hdef,casetype : tdef;
  1059. { maxsize contains the max. size of a variant }
  1060. { startvarrec contains the start of the variant part of a record }
  1061. maxsize, startvarrecsize : longint;
  1062. usedalign,
  1063. maxalignment,startvarrecalign,
  1064. maxpadalign, startpadalign: shortint;
  1065. pt : tnode;
  1066. fieldvs : tfieldvarsym;
  1067. hstaticvs : tglobalvarsym;
  1068. vs : tabstractvarsym;
  1069. srsym : tsym;
  1070. srsymtable : tsymtable;
  1071. recst : tabstractrecordsymtable;
  1072. unionsymtable : trecordsymtable;
  1073. offset : longint;
  1074. uniondef : trecorddef;
  1075. unionsym : tfieldvarsym;
  1076. hintsymoptions : tsymoptions;
  1077. semicoloneaten: boolean;
  1078. {$ifdef powerpc}
  1079. tempdef: tdef;
  1080. is_first_field: boolean;
  1081. {$endif powerpc}
  1082. begin
  1083. recst:=tabstractrecordsymtable(symtablestack.top);
  1084. {$ifdef powerpc}
  1085. is_first_field := true;
  1086. {$endif powerpc}
  1087. old_current_object_option:=current_object_option;
  1088. { all variables are public if not in a object declaration }
  1089. if not(vd_object in options) then
  1090. current_object_option:=[sp_public];
  1091. old_block_type:=block_type;
  1092. block_type:=bt_type;
  1093. { Force an expected ID error message }
  1094. if not (token in [_ID,_CASE,_END]) then
  1095. consume(_ID);
  1096. { read vars }
  1097. sc:=TFPObjectList.create(false);
  1098. while (token=_ID) and
  1099. not((vd_object in options) and
  1100. (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
  1101. begin
  1102. sorg:=orgpattern;
  1103. semicoloneaten:=false;
  1104. sc.clear;
  1105. repeat
  1106. if try_to_consume(_ID) then
  1107. begin
  1108. vs:=tfieldvarsym.create(orgpattern,vs_value,generrordef,[]);
  1109. sc.add(vs);
  1110. recst.insert(vs);
  1111. end;
  1112. until not try_to_consume(_COMMA);
  1113. consume(_COLON);
  1114. { Don't search in the recordsymtable for types }
  1115. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1116. symtablestack.pop(recst);
  1117. ignore_equal:=true;
  1118. read_anon_type(hdef,false);
  1119. ignore_equal:=false;
  1120. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1121. symtablestack.push(recst);
  1122. { Process procvar directives }
  1123. if maybe_parse_proc_directives(hdef) then
  1124. semicoloneaten:=true;
  1125. {$ifdef powerpc}
  1126. { from gcc/gcc/config/rs6000/rs6000.h:
  1127. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1128. /* Return the alignment of a struct based on the Macintosh PowerPC
  1129. alignment rules. In general the alignment of a struct is
  1130. determined by the greatest alignment of its elements. However, the
  1131. PowerPC rules cause the alignment of a struct to peg at word
  1132. alignment except when the first field has greater than word
  1133. (32-bit) alignment, in which case the alignment is determined by
  1134. the alignment of the first field. */
  1135. }
  1136. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and
  1137. is_first_field and
  1138. (symtablestack.top.symtabletype = recordsymtable) and
  1139. (trecordsymtable(symtablestack.top).usefieldalignment = -1) then
  1140. begin
  1141. tempdef := hdef;
  1142. while tempdef.deftype = arraydef do
  1143. tempdef := tarraydef(tempdef).elementdef;
  1144. if tempdef.deftype <> recorddef then
  1145. maxpadalign := tempdef.alignment
  1146. else
  1147. maxpadalign := trecorddef(tempdef).padalignment;
  1148. if (maxpadalign > 4) and
  1149. (maxpadalign > trecordsymtable(symtablestack.top).padalignment) then
  1150. trecordsymtable(symtablestack.top).padalignment := maxpadalign;
  1151. is_first_field := false;
  1152. end;
  1153. {$endif powerpc}
  1154. { types that use init/final are not allowed in variant parts, but
  1155. classes are allowed }
  1156. if (variantrecordlevel>0) and
  1157. (hdef.needs_inittable and not is_class(hdef)) then
  1158. Message(parser_e_cant_use_inittable_here);
  1159. { try to parse the hint directives }
  1160. hintsymoptions:=[];
  1161. try_consume_hintdirective(hintsymoptions);
  1162. { Records and objects can't have default values }
  1163. { for a record there doesn't need to be a ; before the END or ) }
  1164. if not(token in [_END,_RKLAMMER]) and
  1165. not(semicoloneaten) then
  1166. consume(_SEMICOLON);
  1167. { Parse procvar directives after ; }
  1168. maybe_parse_proc_directives(hdef);
  1169. { Add calling convention for procvar }
  1170. if (hdef.deftype=procvardef) and
  1171. (hdef.typesym=nil) then
  1172. handle_calling_convention(tprocvardef(hdef));
  1173. { Check for STATIC directive }
  1174. if (vd_object in options) and
  1175. (cs_static_keyword in current_settings.moduleswitches) and
  1176. (try_to_consume(_STATIC)) then
  1177. begin
  1178. include(current_object_option,sp_static);
  1179. consume(_SEMICOLON);
  1180. end;
  1181. if (sp_published in current_object_option) and
  1182. not(is_class(hdef)) then
  1183. begin
  1184. Message(parser_e_cant_publish_that);
  1185. exclude(current_object_option,sp_published);
  1186. { recover by changing access type to public }
  1187. for i:=0 to sc.count-1 do
  1188. begin
  1189. fieldvs:=tfieldvarsym(sc[i]);
  1190. exclude(fieldvs.symoptions,sp_published);
  1191. include(fieldvs.symoptions,sp_public);
  1192. end;
  1193. end
  1194. else
  1195. if (sp_published in current_object_option) and
  1196. not(oo_can_have_published in tobjectdef(hdef).objectoptions) then
  1197. begin
  1198. Message(parser_e_only_publishable_classes_can__be_published);
  1199. exclude(current_object_option,sp_published);
  1200. end;
  1201. { update variable options }
  1202. for i:=0 to sc.count-1 do
  1203. begin
  1204. fieldvs:=tfieldvarsym(sc[i]);
  1205. fieldvs.vardef:=hdef;
  1206. { insert any additional hint directives }
  1207. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1208. if (sp_static in current_object_option) then
  1209. include(fieldvs.symoptions,sp_static);
  1210. { static data fields are inserted in the globalsymtable }
  1211. if (sp_static in current_object_option) then
  1212. begin
  1213. hstaticvs:=tglobalvarsym.create('$'+lower(symtablestack.top.name^)+'_'+fieldvs.name,vs_value,hdef,[]);
  1214. recst.defowner.owner.insert(hstaticvs);
  1215. insertbssdata(hstaticvs);
  1216. end
  1217. else
  1218. recst.addfield(fieldvs);
  1219. end;
  1220. { restore current_object_option, it can be changed for
  1221. publishing or static }
  1222. current_object_option:=old_current_object_option;
  1223. end;
  1224. { Check for Case }
  1225. if (vd_record in options) and
  1226. try_to_consume(_CASE) then
  1227. begin
  1228. maxsize:=0;
  1229. maxalignment:=0;
  1230. maxpadalign:=0;
  1231. { including a field declaration? }
  1232. fieldvs:=nil;
  1233. sorg:=orgpattern;
  1234. hs:=pattern;
  1235. searchsym(hs,srsym,srsymtable);
  1236. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1237. begin
  1238. consume(_ID);
  1239. consume(_COLON);
  1240. fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1241. symtablestack.top.insert(fieldvs);
  1242. end;
  1243. read_anon_type(casetype,true);
  1244. if assigned(fieldvs) then
  1245. begin
  1246. fieldvs.vardef:=casetype;
  1247. recst.addfield(fieldvs);
  1248. end;
  1249. if not(is_ordinal(casetype))
  1250. {$ifndef cpu64bit}
  1251. or is_64bitint(casetype)
  1252. {$endif cpu64bit}
  1253. then
  1254. Message(type_e_ordinal_expr_expected);
  1255. consume(_OF);
  1256. UnionSymtable:=trecordsymtable.create(current_settings.packrecords);
  1257. UnionDef:=trecorddef.create(unionsymtable);
  1258. uniondef.isunion:=true;
  1259. startvarrecsize:=UnionSymtable.datasize;
  1260. { align the bitpacking to the next byte }
  1261. UnionSymtable.datasize:=startvarrecsize;
  1262. startvarrecalign:=UnionSymtable.fieldalignment;
  1263. startpadalign:=Unionsymtable.padalignment;
  1264. symtablestack.push(UnionSymtable);
  1265. repeat
  1266. repeat
  1267. pt:=comp_expr(true);
  1268. if not(pt.nodetype=ordconstn) then
  1269. Message(parser_e_illegal_expression);
  1270. pt.free;
  1271. if token=_COMMA then
  1272. consume(_COMMA)
  1273. else
  1274. break;
  1275. until false;
  1276. consume(_COLON);
  1277. { read the vars }
  1278. consume(_LKLAMMER);
  1279. inc(variantrecordlevel);
  1280. if token<>_RKLAMMER then
  1281. read_record_fields([vd_record]);
  1282. dec(variantrecordlevel);
  1283. consume(_RKLAMMER);
  1284. { calculates maximal variant size }
  1285. maxsize:=max(maxsize,unionsymtable.datasize);
  1286. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1287. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1288. { the items of the next variant are overlayed }
  1289. unionsymtable.datasize:=startvarrecsize;
  1290. unionsymtable.fieldalignment:=startvarrecalign;
  1291. unionsymtable.padalignment:=startpadalign;
  1292. if (token<>_END) and (token<>_RKLAMMER) then
  1293. consume(_SEMICOLON)
  1294. else
  1295. break;
  1296. until (token=_END) or (token=_RKLAMMER);
  1297. symtablestack.pop(UnionSymtable);
  1298. { at last set the record size to that of the biggest variant }
  1299. unionsymtable.datasize:=maxsize;
  1300. unionsymtable.fieldalignment:=maxalignment;
  1301. UnionSym:=tfieldvarsym.create('$case',vs_value,uniondef,[]);
  1302. unionsymtable.addalignmentpadding;
  1303. {$ifdef powerpc}
  1304. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1305. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and
  1306. is_first_field and
  1307. (recst.usefieldalignment = -1) and
  1308. (maxpadalign > recst.padalignment) then
  1309. recst.padalignment:=maxpadalign;
  1310. {$endif powerpc}
  1311. { Align the offset where the union symtable is added }
  1312. if (recst.usefieldalignment=-1) then
  1313. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign)
  1314. else
  1315. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1316. offset:=align(recst.datasize,usedalign);
  1317. recst.datasize:=offset+unionsymtable.datasize;
  1318. if unionsymtable.recordalignment>recst.fieldalignment then
  1319. recst.fieldalignment:=unionsymtable.recordalignment;
  1320. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  1321. unionsym.free;
  1322. uniondef.free;
  1323. end;
  1324. block_type:=old_block_type;
  1325. current_object_option:=old_current_object_option;
  1326. { free the list }
  1327. sc.free;
  1328. {$ifdef powerpc}
  1329. is_first_field := false;
  1330. {$endif powerpc}
  1331. end;
  1332. end.