pdecvar.pas 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605
  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. procedure read_public_and_external(vs: tabstractvarsym);
  30. implementation
  31. uses
  32. SysUtils,
  33. { common }
  34. cutils,cclasses,
  35. { global }
  36. globtype,globals,tokens,verbose,constexp,
  37. systems,
  38. { symtable }
  39. symconst,symbase,symtype,symtable,defutil,defcmp,
  40. fmodule,htypechk,
  41. { pass 1 }
  42. node,pass_1,aasmdata,
  43. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nmem,nutils,
  44. { codegen }
  45. ncgutil,
  46. { parser }
  47. scanner,
  48. pbase,pexpr,ptype,ptconst,pdecsub,
  49. { link }
  50. import
  51. ;
  52. function read_property_dec(aclass:tobjectdef):tpropertysym;
  53. { convert a node tree to symlist and return the last
  54. symbol }
  55. function parse_symlist(pl:tpropaccesslist;var def:tdef):boolean;
  56. var
  57. idx : longint;
  58. sym : tsym;
  59. srsymtable : TSymtable;
  60. st : TSymtable;
  61. p : tnode;
  62. begin
  63. result:=true;
  64. def:=nil;
  65. if token=_ID then
  66. begin
  67. if assigned(aclass) then
  68. sym:=search_class_member(aclass,pattern)
  69. else
  70. searchsym(pattern,sym,srsymtable);
  71. if assigned(sym) then
  72. begin
  73. case sym.typ of
  74. fieldvarsym :
  75. begin
  76. if (symtablestack.top.currentvisibility<>vis_private) then
  77. addsymref(sym);
  78. pl.addsym(sl_load,sym);
  79. def:=tfieldvarsym(sym).vardef;
  80. end;
  81. procsym :
  82. begin
  83. if (symtablestack.top.currentvisibility<>vis_private) then
  84. addsymref(sym);
  85. pl.addsym(sl_call,sym);
  86. end;
  87. else
  88. begin
  89. Message1(parser_e_illegal_field_or_method,orgpattern);
  90. def:=generrordef;
  91. result:=false;
  92. end;
  93. end;
  94. end
  95. else
  96. begin
  97. Message1(parser_e_illegal_field_or_method,orgpattern);
  98. def:=generrordef;
  99. result:=false;
  100. end;
  101. consume(_ID);
  102. repeat
  103. case token of
  104. _ID,
  105. _SEMICOLON :
  106. begin
  107. break;
  108. end;
  109. _POINT :
  110. begin
  111. consume(_POINT);
  112. if assigned(def) then
  113. begin
  114. st:=def.GetSymtable(gs_record);
  115. if assigned(st) then
  116. begin
  117. sym:=tsym(st.Find(pattern));
  118. if not(assigned(sym)) and is_object(def) then
  119. sym:=search_class_member(tobjectdef(def),pattern);
  120. if assigned(sym) then
  121. begin
  122. pl.addsym(sl_subscript,sym);
  123. case sym.typ of
  124. fieldvarsym :
  125. def:=tfieldvarsym(sym).vardef;
  126. else
  127. begin
  128. Message1(sym_e_illegal_field,orgpattern);
  129. result:=false;
  130. end;
  131. end;
  132. end
  133. else
  134. begin
  135. Message1(sym_e_illegal_field,orgpattern);
  136. result:=false;
  137. end;
  138. end
  139. else
  140. begin
  141. Message(parser_e_invalid_qualifier);
  142. result:=false;
  143. end;
  144. end
  145. else
  146. begin
  147. Message(parser_e_invalid_qualifier);
  148. result:=false;
  149. end;
  150. consume(_ID);
  151. end;
  152. _LECKKLAMMER :
  153. begin
  154. consume(_LECKKLAMMER);
  155. repeat
  156. if def.typ=arraydef then
  157. begin
  158. idx:=0;
  159. p:=comp_expr(true);
  160. if (not codegenerror) then
  161. begin
  162. if (p.nodetype=ordconstn) then
  163. begin
  164. { type/range checking }
  165. inserttypeconv(p,tarraydef(def).rangedef);
  166. if (Tordconstnode(p).value<int64(low(longint))) or
  167. (Tordconstnode(p).value>int64(high(longint))) then
  168. message(parser_e_array_range_out_of_bounds)
  169. else
  170. idx:=Tordconstnode(p).value.svalue
  171. end
  172. else
  173. Message(type_e_ordinal_expr_expected)
  174. end;
  175. pl.addconst(sl_vec,idx,p.resultdef);
  176. p.free;
  177. def:=tarraydef(def).elementdef;
  178. end
  179. else
  180. begin
  181. Message(parser_e_invalid_qualifier);
  182. result:=false;
  183. end;
  184. until not try_to_consume(_COMMA);
  185. consume(_RECKKLAMMER);
  186. end;
  187. else
  188. begin
  189. Message(parser_e_ill_property_access_sym);
  190. result:=false;
  191. break;
  192. end;
  193. end;
  194. until false;
  195. end
  196. else
  197. begin
  198. Message(parser_e_ill_property_access_sym);
  199. result:=false;
  200. end;
  201. end;
  202. function allow_default_property(p : tpropertysym) : boolean;
  203. begin
  204. allow_default_property:=
  205. (is_ordinal(p.propdef) or
  206. {$ifndef cpu64bitaddr}
  207. is_64bitint(p.propdef) or
  208. {$endif cpu64bitaddr}
  209. is_class(p.propdef) or
  210. is_single(p.propdef) or
  211. (p.propdef.typ in [classrefdef,pointerdef]) or
  212. is_smallset(p.propdef)
  213. ) and not
  214. (
  215. (p.propdef.typ=arraydef) and
  216. (ppo_indexed in p.propoptions)
  217. ) and not
  218. (ppo_hasparameters in p.propoptions);
  219. end;
  220. var
  221. sym : tsym;
  222. srsymtable: tsymtable;
  223. p : tpropertysym;
  224. overriden : tsym;
  225. varspez : tvarspez;
  226. hdef : tdef;
  227. arraytype : tdef;
  228. def : tdef;
  229. pt : tnode;
  230. sc : TFPObjectList;
  231. paranr : word;
  232. i : longint;
  233. ImplIntf : TImplementedInterface;
  234. found : boolean;
  235. hreadparavs,
  236. hparavs : tparavarsym;
  237. storedprocdef,
  238. readprocdef,
  239. writeprocdef : tprocvardef;
  240. begin
  241. { Generate temp procvardefs to search for matching read/write
  242. procedures. the readprocdef will store all definitions }
  243. paranr:=0;
  244. readprocdef:=tprocvardef.create(normal_function_level);
  245. writeprocdef:=tprocvardef.create(normal_function_level);
  246. storedprocdef:=tprocvardef.create(normal_function_level);
  247. { make it method pointers }
  248. if assigned(aclass) then
  249. begin
  250. include(readprocdef.procoptions,po_methodpointer);
  251. include(writeprocdef.procoptions,po_methodpointer);
  252. include(storedprocdef.procoptions,po_methodpointer);
  253. end;
  254. { method for stored must return boolean }
  255. storedprocdef.returndef:=booltype;
  256. if token<>_ID then
  257. begin
  258. consume(_ID);
  259. consume(_SEMICOLON);
  260. exit;
  261. end;
  262. { Generate propertysym and insert in symtablestack }
  263. p:=tpropertysym.create(orgpattern);
  264. p.visibility:=symtablestack.top.currentvisibility;
  265. p.default:=longint($80000000);
  266. symtablestack.top.insert(p);
  267. consume(_ID);
  268. { property parameters ? }
  269. if try_to_consume(_LECKKLAMMER) then
  270. begin
  271. if (p.visibility=vis_published) and
  272. not (m_delphi in current_settings.modeswitches) then
  273. Message(parser_e_cant_publish_that_property);
  274. { create a list of the parameters }
  275. symtablestack.push(readprocdef.parast);
  276. sc:=TFPObjectList.create(false);
  277. inc(testcurobject);
  278. repeat
  279. if try_to_consume(_VAR) then
  280. varspez:=vs_var
  281. else if try_to_consume(_CONST) then
  282. varspez:=vs_const
  283. else if (m_out in current_settings.modeswitches) and try_to_consume(_OUT) then
  284. varspez:=vs_out
  285. else
  286. varspez:=vs_value;
  287. sc.clear;
  288. repeat
  289. inc(paranr);
  290. hreadparavs:=tparavarsym.create(orgpattern,10*paranr,varspez,generrordef,[]);
  291. readprocdef.parast.insert(hreadparavs);
  292. sc.add(hreadparavs);
  293. consume(_ID);
  294. until not try_to_consume(_COMMA);
  295. if try_to_consume(_COLON) then
  296. begin
  297. if try_to_consume(_ARRAY) then
  298. begin
  299. consume(_OF);
  300. { define range and type of range }
  301. hdef:=tarraydef.create(0,-1,s32inttype);
  302. { define field type }
  303. single_type(arraytype,false,false);
  304. tarraydef(hdef).elementdef:=arraytype;
  305. end
  306. else
  307. single_type(hdef,false,false);
  308. end
  309. else
  310. hdef:=cformaltype;
  311. for i:=0 to sc.count-1 do
  312. begin
  313. hreadparavs:=tparavarsym(sc[i]);
  314. hreadparavs.vardef:=hdef;
  315. { also update the writeprocdef }
  316. hparavs:=tparavarsym.create(hreadparavs.realname,hreadparavs.paranr,vs_value,hdef,[]);
  317. writeprocdef.parast.insert(hparavs);
  318. end;
  319. until not try_to_consume(_SEMICOLON);
  320. sc.free;
  321. dec(testcurobject);
  322. symtablestack.pop(readprocdef.parast);
  323. consume(_RECKKLAMMER);
  324. { the parser need to know if a property has parameters, the
  325. index parameter doesn't count (PFV) }
  326. if paranr>0 then
  327. include(p.propoptions,ppo_hasparameters);
  328. end;
  329. { overriden property ? }
  330. { force property interface
  331. there is a property parameter
  332. a global property }
  333. if (token=_COLON) or (paranr>0) or (aclass=nil) then
  334. begin
  335. consume(_COLON);
  336. single_type(p.propdef,false,false);
  337. if (idtoken=_INDEX) then
  338. begin
  339. consume(_INDEX);
  340. pt:=comp_expr(true);
  341. { Only allow enum and integer indexes. Convert all integer
  342. values to s32int to be compatible with delphi, because the
  343. procedure matching requires equal parameters }
  344. if is_constnode(pt) and
  345. is_ordinal(pt.resultdef)
  346. {$ifndef cpu64bitaddr}
  347. and (not is_64bitint(pt.resultdef))
  348. {$endif cpu64bitaddr}
  349. then
  350. begin
  351. if is_integer(pt.resultdef) then
  352. inserttypeconv_internal(pt,s32inttype);
  353. p.index:=tordconstnode(pt).value.svalue;
  354. end
  355. else
  356. begin
  357. Message(parser_e_invalid_property_index_value);
  358. p.index:=0;
  359. end;
  360. p.indexdef:=pt.resultdef;
  361. include(p.propoptions,ppo_indexed);
  362. { concat a longint to the para templates }
  363. inc(paranr);
  364. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  365. readprocdef.parast.insert(hparavs);
  366. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  367. writeprocdef.parast.insert(hparavs);
  368. hparavs:=tparavarsym.create('$index',10*paranr,vs_value,p.indexdef,[]);
  369. storedprocdef.parast.insert(hparavs);
  370. pt.free;
  371. end;
  372. end
  373. else
  374. begin
  375. { do an property override }
  376. overriden:=search_class_member(aclass.childof,p.name);
  377. if assigned(overriden) and
  378. (overriden.typ=propertysym) and
  379. not(is_dispinterface(aclass)) then
  380. begin
  381. p.overridenpropsym:=tpropertysym(overriden);
  382. { inherit all type related entries }
  383. p.indexdef:=tpropertysym(overriden).indexdef;
  384. p.propdef:=tpropertysym(overriden).propdef;
  385. p.index:=tpropertysym(overriden).index;
  386. p.default:=tpropertysym(overriden).default;
  387. p.propoptions:=tpropertysym(overriden).propoptions;
  388. end
  389. else
  390. begin
  391. p.propdef:=generrordef;
  392. message(parser_e_no_property_found_to_override);
  393. end;
  394. end;
  395. if ((p.visibility=vis_published) or is_dispinterface(aclass)) and
  396. not(p.propdef.is_publishable) then
  397. begin
  398. Message(parser_e_cant_publish_that_property);
  399. p.visibility:=vis_public;
  400. end;
  401. if not(is_dispinterface(aclass)) then
  402. begin
  403. if try_to_consume(_READ) then
  404. begin
  405. p.propaccesslist[palt_read].clear;
  406. if parse_symlist(p.propaccesslist[palt_read],def) then
  407. begin
  408. sym:=p.propaccesslist[palt_read].firstsym^.sym;
  409. case sym.typ of
  410. procsym :
  411. begin
  412. { read is function returning the type of the property }
  413. readprocdef.returndef:=p.propdef;
  414. { Insert hidden parameters }
  415. handle_calling_convention(readprocdef);
  416. { search procdefs matching readprocdef }
  417. { we ignore hidden stuff here because the property access symbol might have
  418. non default calling conventions which might change the hidden stuff;
  419. see tw3216.pp (FK) }
  420. p.propaccesslist[palt_read].procdef:=Tprocsym(sym).Find_procdef_bypara(readprocdef.paras,p.propdef,[cpo_allowdefaults,cpo_ignorehidden]);
  421. if not assigned(p.propaccesslist[palt_read].procdef) then
  422. Message(parser_e_ill_property_access_sym);
  423. end;
  424. fieldvarsym :
  425. begin
  426. if not assigned(def) then
  427. internalerror(200310071);
  428. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  429. begin
  430. { property parameters are allowed if this is
  431. an indexed property, because the index is then
  432. the parameter.
  433. Note: In the help of Kylix it is written
  434. that it isn't allowed, but the compiler accepts it (PFV) }
  435. if (ppo_hasparameters in p.propoptions) then
  436. Message(parser_e_ill_property_access_sym);
  437. end
  438. else
  439. IncompatibleTypes(def,p.propdef);
  440. end;
  441. else
  442. Message(parser_e_ill_property_access_sym);
  443. end;
  444. end;
  445. end;
  446. if try_to_consume(_WRITE) then
  447. begin
  448. p.propaccesslist[palt_write].clear;
  449. if parse_symlist(p.propaccesslist[palt_write],def) then
  450. begin
  451. sym:=p.propaccesslist[palt_write].firstsym^.sym;
  452. case sym.typ of
  453. procsym :
  454. begin
  455. { write is a procedure with an extra value parameter
  456. of the of the property }
  457. writeprocdef.returndef:=voidtype;
  458. inc(paranr);
  459. hparavs:=tparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  460. writeprocdef.parast.insert(hparavs);
  461. { Insert hidden parameters }
  462. handle_calling_convention(writeprocdef);
  463. { search procdefs matching writeprocdef }
  464. p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults]);
  465. if not assigned(p.propaccesslist[palt_write].procdef) then
  466. Message(parser_e_ill_property_access_sym);
  467. end;
  468. fieldvarsym :
  469. begin
  470. if not assigned(def) then
  471. internalerror(200310072);
  472. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  473. begin
  474. { property parameters are allowed if this is
  475. an indexed property, because the index is then
  476. the parameter.
  477. Note: In the help of Kylix it is written
  478. that it isn't allowed, but the compiler accepts it (PFV) }
  479. if (ppo_hasparameters in p.propoptions) then
  480. Message(parser_e_ill_property_access_sym);
  481. end
  482. else
  483. IncompatibleTypes(def,p.propdef);
  484. end;
  485. else
  486. Message(parser_e_ill_property_access_sym);
  487. end;
  488. end;
  489. end;
  490. end
  491. else
  492. begin
  493. if try_to_consume(_READONLY) then
  494. begin
  495. end
  496. else if try_to_consume(_WRITEONLY) then
  497. begin
  498. end;
  499. if try_to_consume(_DISPID) then
  500. begin
  501. pt:=comp_expr(true);
  502. if is_constintnode(pt) then
  503. // tprocdef(pd).extnumber:=tordconstnode(pt).value
  504. else
  505. Message(parser_e_dispid_must_be_ord_const);
  506. pt.free;
  507. end;
  508. end;
  509. if assigned(aclass) and not(is_dispinterface(aclass)) then
  510. begin
  511. { ppo_stored is default on for not overriden properties }
  512. if not assigned(p.overridenpropsym) then
  513. include(p.propoptions,ppo_stored);
  514. if try_to_consume(_STORED) then
  515. begin
  516. include(p.propoptions,ppo_stored);
  517. p.propaccesslist[palt_stored].clear;
  518. case token of
  519. _ID:
  520. begin
  521. { in the case that idtoken=_DEFAULT }
  522. { we have to do nothing except }
  523. { setting ppo_stored, it's the same }
  524. { as stored true }
  525. if idtoken<>_DEFAULT then
  526. begin
  527. { parse_symlist cannot deal with constsyms, and
  528. we also don't want to put constsyms in symlists
  529. since they have to be evaluated immediately rather
  530. than each time the property is accessed
  531. The proper fix would be to always create a parse tree
  532. and then convert that one, if appropriate, to a symlist.
  533. Currently, we e.g. don't support any constant expressions
  534. yet either here, while Delphi does.
  535. }
  536. { make sure we don't let constants mask class fields/
  537. methods
  538. }
  539. if (not assigned(aclass) or
  540. (search_class_member(aclass,pattern)=nil)) and
  541. searchsym(pattern,sym,srsymtable) and
  542. (sym.typ = constsym) then
  543. begin
  544. addsymref(sym);
  545. if not is_boolean(tconstsym(sym).constdef) then
  546. Message(parser_e_stored_property_must_be_boolean)
  547. else if (tconstsym(sym).value.valueord=0) then
  548. { same as for _FALSE }
  549. exclude(p.propoptions,ppo_stored)
  550. else
  551. { same as for _TRUE }
  552. p.default:=longint($80000000);
  553. consume(_ID);
  554. end
  555. else if parse_symlist(p.propaccesslist[palt_stored],def) then
  556. begin
  557. sym:=p.propaccesslist[palt_stored].firstsym^.sym;
  558. case sym.typ of
  559. procsym :
  560. begin
  561. { Insert hidden parameters }
  562. handle_calling_convention(storedprocdef);
  563. p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
  564. if not assigned(p.propaccesslist[palt_stored].procdef) then
  565. message(parser_e_ill_property_storage_sym);
  566. end;
  567. fieldvarsym :
  568. begin
  569. if not assigned(def) then
  570. internalerror(200310073);
  571. if (ppo_hasparameters in p.propoptions) or
  572. not(is_boolean(def)) then
  573. Message(parser_e_stored_property_must_be_boolean);
  574. end;
  575. else
  576. Message(parser_e_ill_property_access_sym);
  577. end;
  578. end;
  579. end;
  580. end;
  581. _FALSE:
  582. begin
  583. consume(_FALSE);
  584. exclude(p.propoptions,ppo_stored);
  585. end;
  586. _TRUE:
  587. begin
  588. p.default:=longint($80000000);
  589. consume(_TRUE);
  590. end;
  591. end;
  592. end;
  593. end;
  594. if try_to_consume(_DEFAULT) then
  595. begin
  596. if not allow_default_property(p) then
  597. begin
  598. Message(parser_e_property_cant_have_a_default_value);
  599. { Error recovery }
  600. pt:=comp_expr(true);
  601. pt.free;
  602. end
  603. else
  604. begin
  605. { Get the result of the default, the firstpass is
  606. needed to support values like -1 }
  607. pt:=comp_expr(true);
  608. if (p.propdef.typ=setdef) and
  609. (pt.nodetype=arrayconstructorn) then
  610. begin
  611. arrayconstructor_to_set(pt);
  612. do_typecheckpass(pt);
  613. end;
  614. inserttypeconv(pt,p.propdef);
  615. if not(is_constnode(pt)) then
  616. Message(parser_e_property_default_value_must_const);
  617. { Set default value }
  618. case pt.nodetype of
  619. setconstn :
  620. p.default:=plongint(tsetconstnode(pt).value_set)^;
  621. ordconstn :
  622. if (Tordconstnode(pt).value<int64(low(longint))) or
  623. (Tordconstnode(pt).value>int64(high(cardinal))) then
  624. message(parser_e_range_check_error)
  625. else
  626. p.default:=longint(tordconstnode(pt).value.svalue);
  627. niln :
  628. p.default:=0;
  629. realconstn:
  630. p.default:=longint(single(trealconstnode(pt).value_real));
  631. end;
  632. pt.free;
  633. end;
  634. end
  635. else if try_to_consume(_NODEFAULT) then
  636. begin
  637. p.default:=longint($80000000);
  638. end;
  639. (*
  640. else {if allow_default_property(p) then
  641. begin
  642. p.default:=longint($80000000);
  643. end;
  644. *)
  645. { Parse possible "implements" keyword }
  646. if try_to_consume(_IMPLEMENTS) then
  647. begin
  648. single_type(def,false,false);
  649. if not(is_interface(def)) then
  650. message(parser_e_class_implements_must_be_interface);
  651. if is_interface(p.propdef) then
  652. begin
  653. if compare_defs(def,p.propdef,nothingn)<te_equal then
  654. begin
  655. message2(parser_e_implements_must_have_correct_type,def.GetTypeName,p.propdef.GetTypeName);
  656. exit;
  657. end;
  658. end
  659. else if is_class(p.propdef) then
  660. begin
  661. ImplIntf:=tobjectdef(p.propdef).find_implemented_interface(tobjectdef(def));
  662. if assigned(ImplIntf) then
  663. begin
  664. if compare_defs(ImplIntf.IntfDef,def,nothingn)<te_equal then
  665. begin
  666. message2(parser_e_implements_must_have_correct_type,ImplIntf.IntfDef.GetTypeName,def.GetTypeName);
  667. exit;
  668. end;
  669. end
  670. else
  671. begin
  672. message2(parser_e_class_doesnt_implement_interface,p.propdef.GetTypeName,def.GetTypeName);
  673. exit;
  674. end;
  675. end
  676. else
  677. begin
  678. message(parser_e_implements_must_be_class_or_interface);
  679. exit;
  680. end;
  681. if not assigned(p.propaccesslist[palt_read].firstsym) then
  682. begin
  683. message(parser_e_implements_must_read_specifier);
  684. exit;
  685. end;
  686. if assigned(p.propaccesslist[palt_write].firstsym) then
  687. begin
  688. message(parser_e_implements_must_not_have_write_specifier);
  689. exit;
  690. end;
  691. if assigned(p.propaccesslist[palt_stored].firstsym) then
  692. begin
  693. message(parser_e_implements_must_not_have_stored_specifier);
  694. exit;
  695. end;
  696. found:=false;
  697. for i:=0 to aclass.ImplementedInterfaces.Count-1 do
  698. begin
  699. ImplIntf:=TImplementedInterface(aclass.ImplementedInterfaces[i]);
  700. if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
  701. begin
  702. found:=true;
  703. break;
  704. end;
  705. end;
  706. if found then
  707. begin
  708. ImplIntf.ImplementsGetter:=p;
  709. case p.propaccesslist[palt_read].firstsym^.sym.typ of
  710. procsym :
  711. begin
  712. if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) then
  713. ImplIntf.IType:=etVirtualMethodResult
  714. else
  715. ImplIntf.IType:=etStaticMethodResult;
  716. end;
  717. fieldvarsym :
  718. ImplIntf.IType:=etFieldValue;
  719. else
  720. internalerror(200802161);
  721. end;
  722. end
  723. else
  724. message1(parser_e_implements_uses_non_implemented_interface,def.GetTypeName);
  725. end;
  726. { remove temporary procvardefs }
  727. readprocdef.owner.deletedef(readprocdef);
  728. writeprocdef.owner.deletedef(writeprocdef);
  729. result:=p;
  730. end;
  731. function maybe_parse_proc_directives(def:tdef):boolean;
  732. var
  733. newtype : ttypesym;
  734. begin
  735. result:=false;
  736. { Process procvar directives before = and ; }
  737. if (def.typ=procvardef) and
  738. (def.typesym=nil) and
  739. check_proc_directive(true) then
  740. begin
  741. newtype:=ttypesym.create('unnamed',def);
  742. parse_var_proc_directives(tsym(newtype));
  743. newtype.typedef:=nil;
  744. def.typesym:=nil;
  745. newtype.free;
  746. result:=true;
  747. end;
  748. end;
  749. const
  750. variantrecordlevel : longint = 0;
  751. procedure read_public_and_external_sc(sc:TFPObjectList);
  752. var
  753. vs: tabstractvarsym;
  754. begin
  755. { only allowed for one var }
  756. vs:=tabstractvarsym(sc[0]);
  757. if sc.count>1 then
  758. Message(parser_e_absolute_only_one_var);
  759. read_public_and_external(vs);
  760. end;
  761. procedure read_public_and_external(vs: tabstractvarsym);
  762. var
  763. is_dll,
  764. is_cdecl,
  765. is_external_var,
  766. is_weak_external,
  767. is_public_var : boolean;
  768. dll_name,
  769. C_name : string;
  770. begin
  771. { only allowed for one var }
  772. { only allow external and public on global symbols }
  773. if vs.typ<>staticvarsym then
  774. begin
  775. Message(parser_e_no_local_var_external);
  776. exit;
  777. end;
  778. { defaults }
  779. is_dll:=false;
  780. is_cdecl:=false;
  781. is_external_var:=false;
  782. is_public_var:=false;
  783. C_name:=vs.realname;
  784. { macpas specific handling due to some switches}
  785. if (m_mac in current_settings.modeswitches) then
  786. begin
  787. if (cs_external_var in current_settings.localswitches) then
  788. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  789. is_cdecl:=true;
  790. is_external_var:=true;
  791. end
  792. else if (cs_externally_visible in current_settings.localswitches) then
  793. begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
  794. is_cdecl:=true;
  795. is_public_var:=true;
  796. end;
  797. end;
  798. { cdecl }
  799. if try_to_consume(_CVAR) then
  800. begin
  801. consume(_SEMICOLON);
  802. is_cdecl:=true;
  803. end;
  804. { external }
  805. is_weak_external:=try_to_consume(_WEAKEXTERNAL);
  806. if is_weak_external or
  807. try_to_consume(_EXTERNAL) then
  808. begin
  809. is_external_var:=true;
  810. if (idtoken<>_NAME) and (token<>_SEMICOLON) then
  811. begin
  812. is_dll:=true;
  813. dll_name:=get_stringconst;
  814. if ExtractFileExt(dll_name)='' then
  815. dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
  816. end;
  817. if not(is_cdecl) and try_to_consume(_NAME) then
  818. C_name:=get_stringconst;
  819. consume(_SEMICOLON);
  820. end;
  821. { export or public }
  822. if idtoken in [_EXPORT,_PUBLIC] then
  823. begin
  824. consume(_ID);
  825. if is_external_var then
  826. Message(parser_e_not_external_and_export)
  827. else
  828. is_public_var:=true;
  829. if try_to_consume(_NAME) then
  830. C_name:=get_stringconst;
  831. consume(_SEMICOLON);
  832. end;
  833. { Windows uses an indirect reference using import tables }
  834. if is_dll and
  835. (target_info.system in system_all_windows) then
  836. include(vs.varoptions,vo_is_dll_var);
  837. { Add C _ prefix }
  838. if is_cdecl or
  839. (
  840. is_dll and
  841. (target_info.system in systems_darwin)
  842. ) then
  843. C_Name := target_info.Cprefix+C_Name;
  844. if is_public_var then
  845. begin
  846. include(vs.varoptions,vo_is_public);
  847. vs.varregable := vr_none;
  848. { mark as referenced }
  849. inc(vs.refs);
  850. end;
  851. { now we can insert it in the import lib if its a dll, or
  852. add it to the externals }
  853. if is_external_var then
  854. begin
  855. if vo_is_typed_const in vs.varoptions then
  856. Message(parser_e_initialized_not_for_external);
  857. include(vs.varoptions,vo_is_external);
  858. if (is_weak_external) then
  859. begin
  860. if not(target_info.system in system_weak_linking) then
  861. message(parser_e_weak_external_not_supported);
  862. include(vs.varoptions,vo_is_weak_external);
  863. end;
  864. vs.varregable := vr_none;
  865. if is_dll then
  866. current_module.AddExternalImport(dll_name,C_Name,0,true,false)
  867. else
  868. if tf_has_dllscanner in target_info.flags then
  869. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  870. end;
  871. { Set the assembler name }
  872. tstaticvarsym(vs).set_mangledname(C_Name);
  873. end;
  874. procedure read_var_decls(options:Tvar_dec_options);
  875. procedure read_default_value(sc : TFPObjectList);
  876. var
  877. vs : tabstractnormalvarsym;
  878. tcsym : tstaticvarsym;
  879. begin
  880. vs:=tabstractnormalvarsym(sc[0]);
  881. if sc.count>1 then
  882. Message(parser_e_initialized_only_one_var);
  883. if vo_is_thread_var in vs.varoptions then
  884. Message(parser_e_initialized_not_for_threadvar);
  885. consume(_EQUAL);
  886. case vs.typ of
  887. localvarsym :
  888. begin
  889. tcsym:=tstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[]);
  890. include(tcsym.symoptions,sp_internal);
  891. vs.defaultconstsym:=tcsym;
  892. symtablestack.top.insert(tcsym);
  893. read_typed_const(current_asmdata.asmlists[al_typedconsts],tcsym);
  894. end;
  895. staticvarsym :
  896. begin
  897. read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs));
  898. end;
  899. else
  900. internalerror(200611051);
  901. end;
  902. vs.varstate:=vs_initialised;
  903. end;
  904. {$ifdef gpc_mode}
  905. procedure read_gpc_name(sc : TFPObjectList);
  906. var
  907. vs : tabstractnormalvarsym;
  908. C_Name : string;
  909. begin
  910. consume(_ID);
  911. C_Name:=get_stringconst;
  912. vs:=tabstractnormalvarsym(sc[0]);
  913. if sc.count>1 then
  914. Message(parser_e_absolute_only_one_var);
  915. if vs.typ=staticvarsym then
  916. begin
  917. tstaticvarsym(vs).set_mangledname(C_Name);
  918. include(vs.varoptions,vo_is_external);
  919. end
  920. else
  921. Message(parser_e_no_local_var_external);
  922. end;
  923. {$endif}
  924. procedure read_absolute(sc : TFPObjectList);
  925. var
  926. vs : tabstractvarsym;
  927. abssym : tabsolutevarsym;
  928. pt,hp : tnode;
  929. st : tsymtable;
  930. begin
  931. abssym:=nil;
  932. { only allowed for one var }
  933. vs:=tabstractvarsym(sc[0]);
  934. if sc.count>1 then
  935. Message(parser_e_absolute_only_one_var);
  936. if vo_is_typed_const in vs.varoptions then
  937. Message(parser_e_initialized_not_for_external);
  938. { parse the rest }
  939. pt:=expr;
  940. { check allowed absolute types }
  941. if (pt.nodetype=stringconstn) or
  942. (is_constcharnode(pt)) then
  943. begin
  944. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  945. abssym.fileinfo:=vs.fileinfo;
  946. if pt.nodetype=stringconstn then
  947. abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
  948. else
  949. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  950. consume(token);
  951. abssym.abstyp:=toasm;
  952. end
  953. { address }
  954. else if is_constintnode(pt) then
  955. begin
  956. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  957. abssym.fileinfo:=vs.fileinfo;
  958. abssym.abstyp:=toaddr;
  959. {$ifndef cpu64bitaddr}
  960. { on 64 bit systems, abssym.addroffset is a qword and hence this
  961. test is useless (value is a 64 bit entity) and will always fail
  962. for positive values (since int64(high(abssym.addroffset))=-1
  963. }
  964. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  965. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  966. message(parser_e_range_check_error)
  967. else
  968. {$endif}
  969. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  970. {$ifdef i386}
  971. abssym.absseg:=false;
  972. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  973. try_to_consume(_COLON) then
  974. begin
  975. pt.free;
  976. pt:=expr;
  977. if is_constintnode(pt) then
  978. begin
  979. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  980. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  981. message(parser_e_range_check_error)
  982. else
  983. abssym.addroffset:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  984. abssym.absseg:=true;
  985. end
  986. else
  987. Message(type_e_ordinal_expr_expected);
  988. end;
  989. {$endif i386}
  990. end
  991. { variable }
  992. else
  993. begin
  994. { we have to be able to take the address of the absolute
  995. expression
  996. }
  997. valid_for_addr(pt,true);
  998. { remove subscriptn before checking for loadn }
  999. hp:=pt;
  1000. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1001. begin
  1002. { check for implicit dereferencing and reject it }
  1003. if (hp.nodetype in [subscriptn,vecn]) then
  1004. begin
  1005. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1006. break;
  1007. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1008. (pchar_var[5] is a pchar_2_string typeconv ->
  1009. the vecn only sees an array of char)
  1010. I don't know if all of these type conversions are
  1011. possible, but they're definitely all bad.
  1012. }
  1013. if (tunarynode(hp).left.nodetype=typeconvn) and
  1014. (ttypeconvnode(tunarynode(hp).left).convtype in
  1015. [tc_pchar_2_string,tc_pointer_2_array,
  1016. tc_intf_2_string,tc_intf_2_guid,
  1017. tc_dynarray_2_variant,tc_interface_2_variant,
  1018. tc_array_2_dynarray]) then
  1019. break;
  1020. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1021. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1022. break;
  1023. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1024. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1025. break;
  1026. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1027. break;
  1028. end;
  1029. hp:=tunarynode(hp).left;
  1030. end;
  1031. if (hp.nodetype=loadn) then
  1032. begin
  1033. { we should check the result type of loadn }
  1034. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
  1035. Message(parser_e_absolute_only_to_var_or_const);
  1036. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1037. abssym.fileinfo:=vs.fileinfo;
  1038. abssym.abstyp:=tovar;
  1039. abssym.ref:=node_to_propaccesslist(pt);
  1040. { if the sizes are different, can't be a regvar since you }
  1041. { can't be "absolute upper 8 bits of a register" (except }
  1042. { if its a record field of the same size of a record }
  1043. { regvar, but in that case pt.resultdef.size will have }
  1044. { the same size since it refers to the field and not to }
  1045. { the whole record -- which is why we use pt and not hp) }
  1046. { we can't take the size of an open array }
  1047. if is_open_array(pt.resultdef) or
  1048. (vs.vardef.size <> pt.resultdef.size) then
  1049. make_not_regable(pt,[ra_addr_regable]);
  1050. end
  1051. else
  1052. Message(parser_e_absolute_only_to_var_or_const);
  1053. end;
  1054. pt.free;
  1055. { replace old varsym with the new absolutevarsym }
  1056. if assigned(abssym) then
  1057. begin
  1058. st:=vs.owner;
  1059. vs.owner.Delete(vs);
  1060. st.insert(abssym);
  1061. sc[0]:=abssym;
  1062. end;
  1063. end;
  1064. var
  1065. sc : TFPObjectList;
  1066. vs : tabstractvarsym;
  1067. hdef : tdef;
  1068. i : longint;
  1069. semicoloneaten,
  1070. allowdefaultvalue,
  1071. hasdefaultvalue : boolean;
  1072. hintsymoptions : tsymoptions;
  1073. old_block_type : tblock_type;
  1074. begin
  1075. old_block_type:=block_type;
  1076. block_type:=bt_var;
  1077. { Force an expected ID error message }
  1078. if not (token in [_ID,_CASE,_END]) then
  1079. consume(_ID);
  1080. { read vars }
  1081. sc:=TFPObjectList.create(false);
  1082. while (token=_ID) do
  1083. begin
  1084. semicoloneaten:=false;
  1085. hasdefaultvalue:=false;
  1086. allowdefaultvalue:=true;
  1087. sc.clear;
  1088. repeat
  1089. if (token = _ID) then
  1090. begin
  1091. case symtablestack.top.symtabletype of
  1092. localsymtable :
  1093. vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  1094. staticsymtable,
  1095. globalsymtable :
  1096. begin
  1097. vs:=tstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
  1098. if vd_threadvar in options then
  1099. include(vs.varoptions,vo_is_thread_var);
  1100. end;
  1101. else
  1102. internalerror(200411064);
  1103. end;
  1104. sc.add(vs);
  1105. symtablestack.top.insert(vs);
  1106. end;
  1107. consume(_ID);
  1108. until not try_to_consume(_COMMA);
  1109. { read variable type def }
  1110. block_type:=bt_var_type;
  1111. consume(_COLON);
  1112. {$ifdef gpc_mode}
  1113. if (m_gpc in current_settings.modeswitches) and
  1114. (token=_ID) and
  1115. (orgpattern='__asmname__') then
  1116. read_gpc_name(sc);
  1117. {$endif}
  1118. read_anon_type(hdef,false);
  1119. for i:=0 to sc.count-1 do
  1120. begin
  1121. vs:=tabstractvarsym(sc[i]);
  1122. vs.vardef:=hdef;
  1123. end;
  1124. block_type:=bt_var;
  1125. { Process procvar directives }
  1126. if maybe_parse_proc_directives(hdef) then
  1127. semicoloneaten:=true;
  1128. { check for absolute }
  1129. if try_to_consume(_ABSOLUTE) then
  1130. begin
  1131. read_absolute(sc);
  1132. allowdefaultvalue:=false;
  1133. end;
  1134. { Check for EXTERNAL etc directives before a semicolon }
  1135. if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
  1136. begin
  1137. read_public_and_external_sc(sc);
  1138. allowdefaultvalue:=false;
  1139. semicoloneaten:=true;
  1140. end;
  1141. { try to parse the hint directives }
  1142. hintsymoptions:=[];
  1143. try_consume_hintdirective(hintsymoptions);
  1144. for i:=0 to sc.count-1 do
  1145. begin
  1146. vs:=tabstractvarsym(sc[i]);
  1147. vs.symoptions := vs.symoptions + hintsymoptions;
  1148. end;
  1149. { Handling of Delphi typed const = initialized vars }
  1150. if allowdefaultvalue and
  1151. (token=_EQUAL) and
  1152. not(m_tp7 in current_settings.modeswitches) and
  1153. (symtablestack.top.symtabletype<>parasymtable) then
  1154. begin
  1155. { Add calling convention for procvar }
  1156. if (hdef.typ=procvardef) and
  1157. (hdef.typesym=nil) then
  1158. handle_calling_convention(tprocvardef(hdef));
  1159. read_default_value(sc);
  1160. hasdefaultvalue:=true;
  1161. end
  1162. else
  1163. begin
  1164. if not(semicoloneaten) then
  1165. consume(_SEMICOLON);
  1166. end;
  1167. { Support calling convention for procvars after semicolon }
  1168. if not(hasdefaultvalue) and
  1169. (hdef.typ=procvardef) and
  1170. (hdef.typesym=nil) then
  1171. begin
  1172. { Parse procvar directives after ; }
  1173. maybe_parse_proc_directives(hdef);
  1174. { Add calling convention for procvar }
  1175. handle_calling_convention(tprocvardef(hdef));
  1176. { Handling of Delphi typed const = initialized vars }
  1177. if (token=_EQUAL) and
  1178. not(m_tp7 in current_settings.modeswitches) and
  1179. (symtablestack.top.symtabletype<>parasymtable) then
  1180. begin
  1181. read_default_value(sc);
  1182. hasdefaultvalue:=true;
  1183. end;
  1184. end;
  1185. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1186. if (
  1187. (
  1188. (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
  1189. (m_cvar_support in current_settings.modeswitches)
  1190. ) or
  1191. (
  1192. (m_mac in current_settings.modeswitches) and
  1193. (
  1194. (cs_external_var in current_settings.localswitches) or
  1195. (cs_externally_visible in current_settings.localswitches)
  1196. )
  1197. )
  1198. ) then
  1199. read_public_and_external_sc(sc);
  1200. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1201. for i:=0 to sc.count-1 do
  1202. begin
  1203. vs:=tabstractvarsym(sc[i]);
  1204. if (vs.typ=staticvarsym) and
  1205. not(vo_is_typed_const in vs.varoptions) and
  1206. not(vo_is_external in vs.varoptions) then
  1207. insertbssdata(tstaticvarsym(vs));
  1208. end;
  1209. end;
  1210. block_type:=old_block_type;
  1211. { free the list }
  1212. sc.free;
  1213. end;
  1214. procedure read_record_fields(options:Tvar_dec_options);
  1215. var
  1216. sc : TFPObjectList;
  1217. i : longint;
  1218. hs,sorg : string;
  1219. hdef,casetype : tdef;
  1220. { maxsize contains the max. size of a variant }
  1221. { startvarrec contains the start of the variant part of a record }
  1222. maxsize, startvarrecsize : longint;
  1223. usedalign,
  1224. maxalignment,startvarrecalign,
  1225. maxpadalign, startpadalign: shortint;
  1226. pt : tnode;
  1227. fieldvs : tfieldvarsym;
  1228. hstaticvs : tstaticvarsym;
  1229. vs : tabstractvarsym;
  1230. srsym : tsym;
  1231. srsymtable : TSymtable;
  1232. visibility : tvisibility;
  1233. recst : tabstractrecordsymtable;
  1234. unionsymtable : trecordsymtable;
  1235. offset : longint;
  1236. uniondef : trecorddef;
  1237. hintsymoptions : tsymoptions;
  1238. semicoloneaten: boolean;
  1239. is_first_field: boolean;
  1240. {$if defined(powerpc) or defined(powerpc64)}
  1241. tempdef: tdef;
  1242. is_first_type: boolean;
  1243. {$endif powerpc or powerpc64}
  1244. sl : tpropaccesslist;
  1245. begin
  1246. recst:=tabstractrecordsymtable(symtablestack.top);
  1247. is_first_field:=true;
  1248. {$if defined(powerpc) or defined(powerpc64)}
  1249. is_first_type:=true;
  1250. {$endif powerpc or powerpc64}
  1251. { Force an expected ID error message }
  1252. if not (token in [_ID,_CASE,_END]) then
  1253. consume(_ID);
  1254. { read vars }
  1255. sc:=TFPObjectList.create(false);
  1256. while (token=_ID) and
  1257. not((vd_object in options) and
  1258. (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
  1259. begin
  1260. visibility:=symtablestack.top.currentvisibility;
  1261. semicoloneaten:=false;
  1262. sc.clear;
  1263. repeat
  1264. sorg:=orgpattern;
  1265. if token=_ID then
  1266. begin
  1267. vs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1268. sc.add(vs);
  1269. recst.insert(vs);
  1270. end;
  1271. consume(_ID);
  1272. until not try_to_consume(_COMMA);
  1273. consume(_COLON);
  1274. { Don't search in the recordsymtable for types }
  1275. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1276. symtablestack.pop(recst);
  1277. read_anon_type(hdef,false);
  1278. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1279. symtablestack.push(recst);
  1280. { Process procvar directives }
  1281. if maybe_parse_proc_directives(hdef) then
  1282. semicoloneaten:=true;
  1283. {$if defined(powerpc) or defined(powerpc64)}
  1284. { from gcc/gcc/config/rs6000/rs6000.h:
  1285. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1286. /* Return the alignment of a struct based on the Macintosh PowerPC
  1287. alignment rules. In general the alignment of a struct is
  1288. determined by the greatest alignment of its elements. However, the
  1289. PowerPC rules cause the alignment of a struct to peg at word
  1290. alignment except when the first field has greater than word
  1291. (32-bit) alignment, in which case the alignment is determined by
  1292. the alignment of the first field. */
  1293. }
  1294. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1295. is_first_type and
  1296. (symtablestack.top.symtabletype=recordsymtable) and
  1297. (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
  1298. begin
  1299. tempdef:=hdef;
  1300. while tempdef.typ=arraydef do
  1301. tempdef:=tarraydef(tempdef).elementdef;
  1302. if tempdef.typ<>recorddef then
  1303. maxpadalign:=tempdef.alignment
  1304. else
  1305. maxpadalign:=trecorddef(tempdef).padalignment;
  1306. if (maxpadalign>4) and
  1307. (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
  1308. trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
  1309. is_first_type:=false;
  1310. end;
  1311. {$endif powerpc or powerpc64}
  1312. { types that use init/final are not allowed in variant parts, but
  1313. classes are allowed }
  1314. if (variantrecordlevel>0) and
  1315. (hdef.needs_inittable and not is_class(hdef)) then
  1316. Message(parser_e_cant_use_inittable_here);
  1317. { try to parse the hint directives }
  1318. hintsymoptions:=[];
  1319. try_consume_hintdirective(hintsymoptions);
  1320. { mark first field }
  1321. if (is_first_field) then
  1322. begin
  1323. include(tfieldvarsym(sc[0]).varoptions,vo_is_first_field);
  1324. is_first_field:=false;
  1325. end;
  1326. { update variable type and hints }
  1327. for i:=0 to sc.count-1 do
  1328. begin
  1329. fieldvs:=tfieldvarsym(sc[i]);
  1330. fieldvs.vardef:=hdef;
  1331. { insert any additional hint directives }
  1332. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1333. end;
  1334. { Records and objects can't have default values }
  1335. { for a record there doesn't need to be a ; before the END or ) }
  1336. if not(token in [_END,_RKLAMMER]) and
  1337. not(semicoloneaten) then
  1338. consume(_SEMICOLON);
  1339. { Parse procvar directives after ; }
  1340. maybe_parse_proc_directives(hdef);
  1341. { Add calling convention for procvar }
  1342. if (hdef.typ=procvardef) and
  1343. (hdef.typesym=nil) then
  1344. handle_calling_convention(tprocvardef(hdef));
  1345. { Check for STATIC directive }
  1346. if (vd_object in options) and
  1347. (cs_static_keyword in current_settings.moduleswitches) and
  1348. (try_to_consume(_STATIC)) then
  1349. begin
  1350. { add static flag and staticvarsyms }
  1351. for i:=0 to sc.count-1 do
  1352. begin
  1353. fieldvs:=tfieldvarsym(sc[i]);
  1354. include(fieldvs.symoptions,sp_static);
  1355. { generate the symbol which reserves the space }
  1356. hstaticvs:=tstaticvarsym.create('$_static_'+lower(symtablestack.top.name^)+'_'+fieldvs.name,vs_value,hdef,[]);
  1357. recst.defowner.owner.insert(hstaticvs);
  1358. insertbssdata(hstaticvs);
  1359. { generate the symbol for the access }
  1360. sl:=tpropaccesslist.create;
  1361. sl.addsym(sl_load,hstaticvs);
  1362. recst.insert(tabsolutevarsym.create_ref('$'+lower(symtablestack.top.name^)+'_'+fieldvs.name,hdef,sl));
  1363. end;
  1364. consume(_SEMICOLON);
  1365. end;
  1366. if (visibility=vis_published) and
  1367. not(is_class(hdef)) then
  1368. begin
  1369. Message(parser_e_cant_publish_that);
  1370. visibility:=vis_public;
  1371. end;
  1372. if (visibility=vis_published) and
  1373. not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
  1374. not(m_delphi in current_settings.modeswitches) then
  1375. begin
  1376. Message(parser_e_only_publishable_classes_can_be_published);
  1377. visibility:=vis_public;
  1378. end;
  1379. { Generate field in the recordsymtable }
  1380. for i:=0 to sc.count-1 do
  1381. begin
  1382. fieldvs:=tfieldvarsym(sc[i]);
  1383. { static data fields are already inserted in the globalsymtable }
  1384. if not(sp_static in fieldvs.symoptions) then
  1385. recst.addfield(fieldvs,visibility);
  1386. end;
  1387. end;
  1388. { Check for Case }
  1389. if (vd_record in options) and
  1390. try_to_consume(_CASE) then
  1391. begin
  1392. maxsize:=0;
  1393. maxalignment:=0;
  1394. maxpadalign:=0;
  1395. { including a field declaration? }
  1396. fieldvs:=nil;
  1397. sorg:=orgpattern;
  1398. hs:=pattern;
  1399. searchsym(hs,srsym,srsymtable);
  1400. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1401. begin
  1402. consume(_ID);
  1403. consume(_COLON);
  1404. fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1405. symtablestack.top.insert(fieldvs);
  1406. end;
  1407. read_anon_type(casetype,true);
  1408. if assigned(fieldvs) then
  1409. begin
  1410. { mark first field if not yet marked }
  1411. if (is_first_field) then
  1412. begin
  1413. include(fieldvs.varoptions,vo_is_first_field);
  1414. is_first_field:=false;
  1415. end;
  1416. fieldvs.vardef:=casetype;
  1417. recst.addfield(fieldvs,recst.currentvisibility);
  1418. end;
  1419. if not(is_ordinal(casetype))
  1420. {$ifndef cpu64bitaddr}
  1421. or is_64bitint(casetype)
  1422. {$endif cpu64bitaddr}
  1423. then
  1424. Message(type_e_ordinal_expr_expected);
  1425. consume(_OF);
  1426. UnionSymtable:=trecordsymtable.create(current_settings.packrecords);
  1427. UnionDef:=trecorddef.create(unionsymtable);
  1428. uniondef.isunion:=true;
  1429. startvarrecsize:=UnionSymtable.datasize;
  1430. { align the bitpacking to the next byte }
  1431. UnionSymtable.datasize:=startvarrecsize;
  1432. startvarrecalign:=UnionSymtable.fieldalignment;
  1433. startpadalign:=Unionsymtable.padalignment;
  1434. symtablestack.push(UnionSymtable);
  1435. repeat
  1436. repeat
  1437. pt:=comp_expr(true);
  1438. if not(pt.nodetype=ordconstn) then
  1439. Message(parser_e_illegal_expression);
  1440. if try_to_consume(_POINTPOINT) then
  1441. pt:=crangenode.create(pt,comp_expr(true));
  1442. pt.free;
  1443. if token=_COMMA then
  1444. consume(_COMMA)
  1445. else
  1446. break;
  1447. until false;
  1448. consume(_COLON);
  1449. { read the vars }
  1450. consume(_LKLAMMER);
  1451. inc(variantrecordlevel);
  1452. if token<>_RKLAMMER then
  1453. read_record_fields([vd_record]);
  1454. dec(variantrecordlevel);
  1455. consume(_RKLAMMER);
  1456. { calculates maximal variant size }
  1457. maxsize:=max(maxsize,unionsymtable.datasize);
  1458. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1459. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1460. { the items of the next variant are overlayed }
  1461. unionsymtable.datasize:=startvarrecsize;
  1462. unionsymtable.fieldalignment:=startvarrecalign;
  1463. unionsymtable.padalignment:=startpadalign;
  1464. if (token<>_END) and (token<>_RKLAMMER) then
  1465. consume(_SEMICOLON)
  1466. else
  1467. break;
  1468. until (token=_END) or (token=_RKLAMMER);
  1469. symtablestack.pop(UnionSymtable);
  1470. { at last set the record size to that of the biggest variant }
  1471. unionsymtable.datasize:=maxsize;
  1472. unionsymtable.fieldalignment:=maxalignment;
  1473. unionsymtable.addalignmentpadding;
  1474. {$if defined(powerpc) or defined(powerpc64)}
  1475. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1476. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1477. is_first_type and
  1478. (recst.usefieldalignment=C_alignment) and
  1479. (maxpadalign>recst.padalignment) then
  1480. recst.padalignment:=maxpadalign;
  1481. {$endif powerpc or powerpc64}
  1482. { Align the offset where the union symtable is added }
  1483. case recst.usefieldalignment of
  1484. { allow the unionsymtable to be aligned however it wants }
  1485. { (within the global min/max limits) }
  1486. 0, { default }
  1487. C_alignment:
  1488. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  1489. { 1 byte alignment if we are bitpacked }
  1490. bit_alignment:
  1491. usedalign:=1;
  1492. { otherwise alignment at the packrecords alignment of the }
  1493. { current record }
  1494. else
  1495. usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1496. end;
  1497. offset:=align(recst.datasize,usedalign);
  1498. recst.datasize:=offset+unionsymtable.datasize;
  1499. if unionsymtable.recordalignment>recst.fieldalignment then
  1500. recst.fieldalignment:=unionsymtable.recordalignment;
  1501. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  1502. uniondef.owner.deletedef(uniondef);
  1503. end;
  1504. { free the list }
  1505. sc.free;
  1506. {$ifdef powerpc}
  1507. is_first_type := false;
  1508. {$endif powerpc}
  1509. end;
  1510. end.