pdecvar.pas 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  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. ImplIntf.VtblImplIntf:=ImplIntf;
  710. case p.propaccesslist[palt_read].firstsym^.sym.typ of
  711. procsym :
  712. begin
  713. if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) then
  714. ImplIntf.IType:=etVirtualMethodResult
  715. else
  716. ImplIntf.IType:=etStaticMethodResult;
  717. end;
  718. fieldvarsym :
  719. begin
  720. ImplIntf.IType:=etFieldValue;
  721. { this must be done more sophisticated, here is also probably the wrong place }
  722. ImplIntf.IOffset:=tfieldvarsym(p.propaccesslist[palt_read].firstsym^.sym).fieldoffset;
  723. end
  724. else
  725. internalerror(200802161);
  726. end;
  727. end
  728. else
  729. message1(parser_e_implements_uses_non_implemented_interface,def.GetTypeName);
  730. end;
  731. { remove temporary procvardefs }
  732. readprocdef.owner.deletedef(readprocdef);
  733. writeprocdef.owner.deletedef(writeprocdef);
  734. result:=p;
  735. end;
  736. function maybe_parse_proc_directives(def:tdef):boolean;
  737. var
  738. newtype : ttypesym;
  739. begin
  740. result:=false;
  741. { Process procvar directives before = and ; }
  742. if (def.typ=procvardef) and
  743. (def.typesym=nil) and
  744. check_proc_directive(true) then
  745. begin
  746. newtype:=ttypesym.create('unnamed',def);
  747. parse_var_proc_directives(tsym(newtype));
  748. newtype.typedef:=nil;
  749. def.typesym:=nil;
  750. newtype.free;
  751. result:=true;
  752. end;
  753. end;
  754. const
  755. variantrecordlevel : longint = 0;
  756. procedure read_public_and_external_sc(sc:TFPObjectList);
  757. var
  758. vs: tabstractvarsym;
  759. begin
  760. { only allowed for one var }
  761. vs:=tabstractvarsym(sc[0]);
  762. if sc.count>1 then
  763. Message(parser_e_absolute_only_one_var);
  764. read_public_and_external(vs);
  765. end;
  766. procedure read_public_and_external(vs: tabstractvarsym);
  767. var
  768. is_dll,
  769. is_cdecl,
  770. is_external_var,
  771. is_weak_external,
  772. is_public_var : boolean;
  773. dll_name,
  774. C_name : string;
  775. begin
  776. { only allowed for one var }
  777. { only allow external and public on global symbols }
  778. if vs.typ<>staticvarsym then
  779. begin
  780. Message(parser_e_no_local_var_external);
  781. exit;
  782. end;
  783. { defaults }
  784. is_dll:=false;
  785. is_cdecl:=false;
  786. is_external_var:=false;
  787. is_public_var:=false;
  788. C_name:=vs.realname;
  789. { macpas specific handling due to some switches}
  790. if (m_mac in current_settings.modeswitches) then
  791. begin
  792. if (cs_external_var in current_settings.localswitches) then
  793. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  794. is_cdecl:=true;
  795. is_external_var:=true;
  796. end
  797. else if (cs_externally_visible in current_settings.localswitches) then
  798. begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
  799. is_cdecl:=true;
  800. is_public_var:=true;
  801. end;
  802. end;
  803. { cdecl }
  804. if try_to_consume(_CVAR) then
  805. begin
  806. consume(_SEMICOLON);
  807. is_cdecl:=true;
  808. end;
  809. { external }
  810. is_weak_external:=try_to_consume(_WEAKEXTERNAL);
  811. if is_weak_external or
  812. try_to_consume(_EXTERNAL) then
  813. begin
  814. is_external_var:=true;
  815. if (idtoken<>_NAME) and (token<>_SEMICOLON) then
  816. begin
  817. is_dll:=true;
  818. dll_name:=get_stringconst;
  819. if ExtractFileExt(dll_name)='' then
  820. dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
  821. end;
  822. if not(is_cdecl) and try_to_consume(_NAME) then
  823. C_name:=get_stringconst;
  824. consume(_SEMICOLON);
  825. end;
  826. { export or public }
  827. if idtoken in [_EXPORT,_PUBLIC] then
  828. begin
  829. consume(_ID);
  830. if is_external_var then
  831. Message(parser_e_not_external_and_export)
  832. else
  833. is_public_var:=true;
  834. if try_to_consume(_NAME) then
  835. C_name:=get_stringconst;
  836. consume(_SEMICOLON);
  837. end;
  838. { Windows uses an indirect reference using import tables }
  839. if is_dll and
  840. (target_info.system in system_all_windows) then
  841. include(vs.varoptions,vo_is_dll_var);
  842. { Add C _ prefix }
  843. if is_cdecl or
  844. (
  845. is_dll and
  846. (target_info.system in systems_darwin)
  847. ) then
  848. C_Name := target_info.Cprefix+C_Name;
  849. if is_public_var then
  850. begin
  851. include(vs.varoptions,vo_is_public);
  852. vs.varregable := vr_none;
  853. { mark as referenced }
  854. inc(vs.refs);
  855. end;
  856. { now we can insert it in the import lib if its a dll, or
  857. add it to the externals }
  858. if is_external_var then
  859. begin
  860. if vo_is_typed_const in vs.varoptions then
  861. Message(parser_e_initialized_not_for_external);
  862. include(vs.varoptions,vo_is_external);
  863. if (is_weak_external) then
  864. begin
  865. if not(target_info.system in system_weak_linking) then
  866. message(parser_e_weak_external_not_supported);
  867. include(vs.varoptions,vo_is_weak_external);
  868. end;
  869. vs.varregable := vr_none;
  870. if is_dll then
  871. current_module.AddExternalImport(dll_name,C_Name,0,true,false)
  872. else
  873. if tf_has_dllscanner in target_info.flags then
  874. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  875. end;
  876. { Set the assembler name }
  877. tstaticvarsym(vs).set_mangledname(C_Name);
  878. end;
  879. procedure read_var_decls(options:Tvar_dec_options);
  880. procedure read_default_value(sc : TFPObjectList);
  881. var
  882. vs : tabstractnormalvarsym;
  883. tcsym : tstaticvarsym;
  884. begin
  885. vs:=tabstractnormalvarsym(sc[0]);
  886. if sc.count>1 then
  887. Message(parser_e_initialized_only_one_var);
  888. if vo_is_thread_var in vs.varoptions then
  889. Message(parser_e_initialized_not_for_threadvar);
  890. consume(_EQUAL);
  891. case vs.typ of
  892. localvarsym :
  893. begin
  894. tcsym:=tstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[]);
  895. include(tcsym.symoptions,sp_internal);
  896. vs.defaultconstsym:=tcsym;
  897. symtablestack.top.insert(tcsym);
  898. read_typed_const(current_asmdata.asmlists[al_typedconsts],tcsym);
  899. end;
  900. staticvarsym :
  901. begin
  902. read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs));
  903. end;
  904. else
  905. internalerror(200611051);
  906. end;
  907. vs.varstate:=vs_initialised;
  908. end;
  909. {$ifdef gpc_mode}
  910. procedure read_gpc_name(sc : TFPObjectList);
  911. var
  912. vs : tabstractnormalvarsym;
  913. C_Name : string;
  914. begin
  915. consume(_ID);
  916. C_Name:=get_stringconst;
  917. vs:=tabstractnormalvarsym(sc[0]);
  918. if sc.count>1 then
  919. Message(parser_e_absolute_only_one_var);
  920. if vs.typ=staticvarsym then
  921. begin
  922. tstaticvarsym(vs).set_mangledname(C_Name);
  923. include(vs.varoptions,vo_is_external);
  924. end
  925. else
  926. Message(parser_e_no_local_var_external);
  927. end;
  928. {$endif}
  929. procedure read_absolute(sc : TFPObjectList);
  930. var
  931. vs : tabstractvarsym;
  932. abssym : tabsolutevarsym;
  933. pt,hp : tnode;
  934. st : tsymtable;
  935. {$ifdef i386}
  936. tmpaddr : int64;
  937. {$endif}
  938. begin
  939. abssym:=nil;
  940. { only allowed for one var }
  941. vs:=tabstractvarsym(sc[0]);
  942. if sc.count>1 then
  943. Message(parser_e_absolute_only_one_var);
  944. if vo_is_typed_const in vs.varoptions then
  945. Message(parser_e_initialized_not_for_external);
  946. { parse the rest }
  947. pt:=expr;
  948. { check allowed absolute types }
  949. if (pt.nodetype=stringconstn) or
  950. (is_constcharnode(pt)) then
  951. begin
  952. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  953. abssym.fileinfo:=vs.fileinfo;
  954. if pt.nodetype=stringconstn then
  955. abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
  956. else
  957. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  958. consume(token);
  959. abssym.abstyp:=toasm;
  960. end
  961. { address }
  962. else if is_constintnode(pt) then
  963. begin
  964. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  965. abssym.fileinfo:=vs.fileinfo;
  966. abssym.abstyp:=toaddr;
  967. {$ifndef cpu64bitaddr}
  968. { on 64 bit systems, abssym.addroffset is a qword and hence this
  969. test is useless (value is a 64 bit entity) and will always fail
  970. for positive values (since int64(high(abssym.addroffset))=-1
  971. }
  972. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  973. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  974. message(parser_e_range_check_error)
  975. else
  976. {$endif}
  977. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  978. {$ifdef i386}
  979. abssym.absseg:=false;
  980. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  981. try_to_consume(_COLON) then
  982. begin
  983. pt.free;
  984. pt:=expr;
  985. if is_constintnode(pt) then
  986. begin
  987. tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  988. if (tmpaddr<int64(low(abssym.addroffset))) or
  989. (tmpaddr>int64(high(abssym.addroffset))) then
  990. message(parser_e_range_check_error)
  991. else
  992. abssym.addroffset:=tmpaddr;
  993. abssym.absseg:=true;
  994. end
  995. else
  996. Message(type_e_ordinal_expr_expected);
  997. end;
  998. {$endif i386}
  999. end
  1000. { variable }
  1001. else
  1002. begin
  1003. { we have to be able to take the address of the absolute
  1004. expression
  1005. }
  1006. valid_for_addr(pt,true);
  1007. { remove subscriptn before checking for loadn }
  1008. hp:=pt;
  1009. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1010. begin
  1011. { check for implicit dereferencing and reject it }
  1012. if (hp.nodetype in [subscriptn,vecn]) then
  1013. begin
  1014. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1015. break;
  1016. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1017. (pchar_var[5] is a pchar_2_string typeconv ->
  1018. the vecn only sees an array of char)
  1019. I don't know if all of these type conversions are
  1020. possible, but they're definitely all bad.
  1021. }
  1022. if (tunarynode(hp).left.nodetype=typeconvn) and
  1023. (ttypeconvnode(tunarynode(hp).left).convtype in
  1024. [tc_pchar_2_string,tc_pointer_2_array,
  1025. tc_intf_2_string,tc_intf_2_guid,
  1026. tc_dynarray_2_variant,tc_interface_2_variant,
  1027. tc_array_2_dynarray]) then
  1028. break;
  1029. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1030. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1031. break;
  1032. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1033. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1034. break;
  1035. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1036. break;
  1037. end;
  1038. hp:=tunarynode(hp).left;
  1039. end;
  1040. if (hp.nodetype=loadn) then
  1041. begin
  1042. { we should check the result type of loadn }
  1043. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
  1044. Message(parser_e_absolute_only_to_var_or_const);
  1045. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1046. abssym.fileinfo:=vs.fileinfo;
  1047. abssym.abstyp:=tovar;
  1048. abssym.ref:=node_to_propaccesslist(pt);
  1049. { if the sizes are different, can't be a regvar since you }
  1050. { can't be "absolute upper 8 bits of a register" (except }
  1051. { if its a record field of the same size of a record }
  1052. { regvar, but in that case pt.resultdef.size will have }
  1053. { the same size since it refers to the field and not to }
  1054. { the whole record -- which is why we use pt and not hp) }
  1055. { we can't take the size of an open array }
  1056. if is_open_array(pt.resultdef) or
  1057. (vs.vardef.size <> pt.resultdef.size) then
  1058. make_not_regable(pt,[ra_addr_regable]);
  1059. end
  1060. else
  1061. Message(parser_e_absolute_only_to_var_or_const);
  1062. end;
  1063. pt.free;
  1064. { replace old varsym with the new absolutevarsym }
  1065. if assigned(abssym) then
  1066. begin
  1067. st:=vs.owner;
  1068. vs.owner.Delete(vs);
  1069. st.insert(abssym);
  1070. sc[0]:=abssym;
  1071. end;
  1072. end;
  1073. var
  1074. sc : TFPObjectList;
  1075. vs : tabstractvarsym;
  1076. hdef : tdef;
  1077. i : longint;
  1078. semicoloneaten,
  1079. allowdefaultvalue,
  1080. hasdefaultvalue : boolean;
  1081. hintsymoptions : tsymoptions;
  1082. old_block_type : tblock_type;
  1083. begin
  1084. old_block_type:=block_type;
  1085. block_type:=bt_var;
  1086. { Force an expected ID error message }
  1087. if not (token in [_ID,_CASE,_END]) then
  1088. consume(_ID);
  1089. { read vars }
  1090. sc:=TFPObjectList.create(false);
  1091. while (token=_ID) do
  1092. begin
  1093. semicoloneaten:=false;
  1094. hasdefaultvalue:=false;
  1095. allowdefaultvalue:=true;
  1096. sc.clear;
  1097. repeat
  1098. if (token = _ID) then
  1099. begin
  1100. case symtablestack.top.symtabletype of
  1101. localsymtable :
  1102. vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  1103. staticsymtable,
  1104. globalsymtable :
  1105. begin
  1106. vs:=tstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
  1107. if vd_threadvar in options then
  1108. include(vs.varoptions,vo_is_thread_var);
  1109. end;
  1110. else
  1111. internalerror(200411064);
  1112. end;
  1113. sc.add(vs);
  1114. symtablestack.top.insert(vs);
  1115. end;
  1116. consume(_ID);
  1117. until not try_to_consume(_COMMA);
  1118. { read variable type def }
  1119. block_type:=bt_var_type;
  1120. consume(_COLON);
  1121. {$ifdef gpc_mode}
  1122. if (m_gpc in current_settings.modeswitches) and
  1123. (token=_ID) and
  1124. (orgpattern='__asmname__') then
  1125. read_gpc_name(sc);
  1126. {$endif}
  1127. read_anon_type(hdef,false);
  1128. for i:=0 to sc.count-1 do
  1129. begin
  1130. vs:=tabstractvarsym(sc[i]);
  1131. vs.vardef:=hdef;
  1132. end;
  1133. block_type:=bt_var;
  1134. { Process procvar directives }
  1135. if maybe_parse_proc_directives(hdef) then
  1136. semicoloneaten:=true;
  1137. { check for absolute }
  1138. if try_to_consume(_ABSOLUTE) then
  1139. begin
  1140. read_absolute(sc);
  1141. allowdefaultvalue:=false;
  1142. end;
  1143. { Check for EXTERNAL etc directives before a semicolon }
  1144. if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
  1145. begin
  1146. read_public_and_external_sc(sc);
  1147. allowdefaultvalue:=false;
  1148. semicoloneaten:=true;
  1149. end;
  1150. { try to parse the hint directives }
  1151. hintsymoptions:=[];
  1152. try_consume_hintdirective(hintsymoptions);
  1153. for i:=0 to sc.count-1 do
  1154. begin
  1155. vs:=tabstractvarsym(sc[i]);
  1156. vs.symoptions := vs.symoptions + hintsymoptions;
  1157. end;
  1158. { Handling of Delphi typed const = initialized vars }
  1159. if allowdefaultvalue and
  1160. (token=_EQUAL) and
  1161. not(m_tp7 in current_settings.modeswitches) and
  1162. (symtablestack.top.symtabletype<>parasymtable) then
  1163. begin
  1164. { Add calling convention for procvar }
  1165. if (hdef.typ=procvardef) and
  1166. (hdef.typesym=nil) then
  1167. handle_calling_convention(tprocvardef(hdef));
  1168. read_default_value(sc);
  1169. hasdefaultvalue:=true;
  1170. end
  1171. else
  1172. begin
  1173. if not(semicoloneaten) then
  1174. consume(_SEMICOLON);
  1175. end;
  1176. { Support calling convention for procvars after semicolon }
  1177. if not(hasdefaultvalue) and
  1178. (hdef.typ=procvardef) and
  1179. (hdef.typesym=nil) then
  1180. begin
  1181. { Parse procvar directives after ; }
  1182. maybe_parse_proc_directives(hdef);
  1183. { Add calling convention for procvar }
  1184. handle_calling_convention(tprocvardef(hdef));
  1185. { Handling of Delphi typed const = initialized vars }
  1186. if (token=_EQUAL) and
  1187. not(m_tp7 in current_settings.modeswitches) and
  1188. (symtablestack.top.symtabletype<>parasymtable) then
  1189. begin
  1190. read_default_value(sc);
  1191. hasdefaultvalue:=true;
  1192. end;
  1193. end;
  1194. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1195. if (
  1196. (
  1197. (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
  1198. (m_cvar_support in current_settings.modeswitches)
  1199. ) or
  1200. (
  1201. (m_mac in current_settings.modeswitches) and
  1202. (
  1203. (cs_external_var in current_settings.localswitches) or
  1204. (cs_externally_visible in current_settings.localswitches)
  1205. )
  1206. )
  1207. ) then
  1208. read_public_and_external_sc(sc);
  1209. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1210. for i:=0 to sc.count-1 do
  1211. begin
  1212. vs:=tabstractvarsym(sc[i]);
  1213. if (vs.typ=staticvarsym) and
  1214. not(vo_is_typed_const in vs.varoptions) and
  1215. not(vo_is_external in vs.varoptions) then
  1216. insertbssdata(tstaticvarsym(vs));
  1217. end;
  1218. end;
  1219. block_type:=old_block_type;
  1220. { free the list }
  1221. sc.free;
  1222. end;
  1223. procedure read_record_fields(options:Tvar_dec_options);
  1224. var
  1225. sc : TFPObjectList;
  1226. i : longint;
  1227. hs,sorg : string;
  1228. hdef,casetype : tdef;
  1229. { maxsize contains the max. size of a variant }
  1230. { startvarrec contains the start of the variant part of a record }
  1231. maxsize, startvarrecsize : longint;
  1232. usedalign,
  1233. maxalignment,startvarrecalign,
  1234. maxpadalign, startpadalign: shortint;
  1235. pt : tnode;
  1236. fieldvs : tfieldvarsym;
  1237. hstaticvs : tstaticvarsym;
  1238. vs : tabstractvarsym;
  1239. srsym : tsym;
  1240. srsymtable : TSymtable;
  1241. visibility : tvisibility;
  1242. recst : tabstractrecordsymtable;
  1243. unionsymtable : trecordsymtable;
  1244. offset : longint;
  1245. uniondef : trecorddef;
  1246. hintsymoptions : tsymoptions;
  1247. semicoloneaten: boolean;
  1248. {$if defined(powerpc) or defined(powerpc64)}
  1249. tempdef: tdef;
  1250. is_first_field: boolean;
  1251. {$endif powerpc or powerpc64}
  1252. sl : tpropaccesslist;
  1253. begin
  1254. recst:=tabstractrecordsymtable(symtablestack.top);
  1255. {$if defined(powerpc) or defined(powerpc64)}
  1256. is_first_field := true;
  1257. {$endif powerpc or powerpc64}
  1258. { Force an expected ID error message }
  1259. if not (token in [_ID,_CASE,_END]) then
  1260. consume(_ID);
  1261. { read vars }
  1262. sc:=TFPObjectList.create(false);
  1263. while (token=_ID) and
  1264. not((vd_object in options) and
  1265. (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
  1266. begin
  1267. visibility:=symtablestack.top.currentvisibility;
  1268. semicoloneaten:=false;
  1269. sc.clear;
  1270. repeat
  1271. sorg:=orgpattern;
  1272. if token=_ID then
  1273. begin
  1274. vs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1275. sc.add(vs);
  1276. recst.insert(vs);
  1277. end;
  1278. consume(_ID);
  1279. until not try_to_consume(_COMMA);
  1280. consume(_COLON);
  1281. { Don't search in the recordsymtable for types }
  1282. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1283. symtablestack.pop(recst);
  1284. read_anon_type(hdef,false);
  1285. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1286. symtablestack.push(recst);
  1287. { Process procvar directives }
  1288. if maybe_parse_proc_directives(hdef) then
  1289. semicoloneaten:=true;
  1290. {$if defined(powerpc) or defined(powerpc64)}
  1291. { from gcc/gcc/config/rs6000/rs6000.h:
  1292. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1293. /* Return the alignment of a struct based on the Macintosh PowerPC
  1294. alignment rules. In general the alignment of a struct is
  1295. determined by the greatest alignment of its elements. However, the
  1296. PowerPC rules cause the alignment of a struct to peg at word
  1297. alignment except when the first field has greater than word
  1298. (32-bit) alignment, in which case the alignment is determined by
  1299. the alignment of the first field. */
  1300. }
  1301. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1302. is_first_field and
  1303. (symtablestack.top.symtabletype=recordsymtable) and
  1304. (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
  1305. begin
  1306. tempdef:=hdef;
  1307. while tempdef.typ=arraydef do
  1308. tempdef:=tarraydef(tempdef).elementdef;
  1309. if tempdef.typ<>recorddef then
  1310. maxpadalign:=tempdef.alignment
  1311. else
  1312. maxpadalign:=trecorddef(tempdef).padalignment;
  1313. if (maxpadalign>4) and
  1314. (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
  1315. trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
  1316. is_first_field:=false;
  1317. end;
  1318. {$endif powerpc or powerpc64}
  1319. { types that use init/final are not allowed in variant parts, but
  1320. classes are allowed }
  1321. if (variantrecordlevel>0) and
  1322. (hdef.needs_inittable and not is_class(hdef)) then
  1323. Message(parser_e_cant_use_inittable_here);
  1324. { try to parse the hint directives }
  1325. hintsymoptions:=[];
  1326. try_consume_hintdirective(hintsymoptions);
  1327. { update variable type and hints }
  1328. for i:=0 to sc.count-1 do
  1329. begin
  1330. fieldvs:=tfieldvarsym(sc[i]);
  1331. fieldvs.vardef:=hdef;
  1332. { insert any additional hint directives }
  1333. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1334. end;
  1335. { Records and objects can't have default values }
  1336. { for a record there doesn't need to be a ; before the END or ) }
  1337. if not(token in [_END,_RKLAMMER]) and
  1338. not(semicoloneaten) then
  1339. consume(_SEMICOLON);
  1340. { Parse procvar directives after ; }
  1341. maybe_parse_proc_directives(hdef);
  1342. { Add calling convention for procvar }
  1343. if (hdef.typ=procvardef) and
  1344. (hdef.typesym=nil) then
  1345. handle_calling_convention(tprocvardef(hdef));
  1346. { Check for STATIC directive }
  1347. if (vd_object in options) and
  1348. (cs_static_keyword in current_settings.moduleswitches) and
  1349. (try_to_consume(_STATIC)) then
  1350. begin
  1351. { add static flag and staticvarsyms }
  1352. for i:=0 to sc.count-1 do
  1353. begin
  1354. fieldvs:=tfieldvarsym(sc[i]);
  1355. include(fieldvs.symoptions,sp_static);
  1356. { generate the symbol which reserves the space }
  1357. hstaticvs:=tstaticvarsym.create('$_static_'+lower(symtablestack.top.name^)+'_'+fieldvs.name,vs_value,hdef,[]);
  1358. recst.defowner.owner.insert(hstaticvs);
  1359. insertbssdata(hstaticvs);
  1360. { generate the symbol for the access }
  1361. sl:=tpropaccesslist.create;
  1362. sl.addsym(sl_load,hstaticvs);
  1363. recst.insert(tabsolutevarsym.create_ref('$'+lower(symtablestack.top.name^)+'_'+fieldvs.name,hdef,sl));
  1364. end;
  1365. consume(_SEMICOLON);
  1366. end;
  1367. if (visibility=vis_published) and
  1368. not(is_class(hdef)) then
  1369. begin
  1370. Message(parser_e_cant_publish_that);
  1371. visibility:=vis_public;
  1372. end;
  1373. if (visibility=vis_published) and
  1374. not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
  1375. not(m_delphi in current_settings.modeswitches) then
  1376. begin
  1377. Message(parser_e_only_publishable_classes_can_be_published);
  1378. visibility:=vis_public;
  1379. end;
  1380. { Generate field in the recordsymtable }
  1381. for i:=0 to sc.count-1 do
  1382. begin
  1383. fieldvs:=tfieldvarsym(sc[i]);
  1384. { static data fields are already inserted in the globalsymtable }
  1385. if not(sp_static in fieldvs.symoptions) then
  1386. recst.addfield(fieldvs,visibility);
  1387. end;
  1388. end;
  1389. { Check for Case }
  1390. if (vd_record in options) and
  1391. try_to_consume(_CASE) then
  1392. begin
  1393. maxsize:=0;
  1394. maxalignment:=0;
  1395. maxpadalign:=0;
  1396. { including a field declaration? }
  1397. fieldvs:=nil;
  1398. sorg:=orgpattern;
  1399. hs:=pattern;
  1400. searchsym(hs,srsym,srsymtable);
  1401. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1402. begin
  1403. consume(_ID);
  1404. consume(_COLON);
  1405. fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1406. symtablestack.top.insert(fieldvs);
  1407. end;
  1408. read_anon_type(casetype,true);
  1409. if assigned(fieldvs) then
  1410. begin
  1411. fieldvs.vardef:=casetype;
  1412. recst.addfield(fieldvs,recst.currentvisibility);
  1413. end;
  1414. if not(is_ordinal(casetype))
  1415. {$ifndef cpu64bitaddr}
  1416. or is_64bitint(casetype)
  1417. {$endif cpu64bitaddr}
  1418. then
  1419. Message(type_e_ordinal_expr_expected);
  1420. consume(_OF);
  1421. UnionSymtable:=trecordsymtable.create(current_settings.packrecords);
  1422. UnionDef:=trecorddef.create(unionsymtable);
  1423. uniondef.isunion:=true;
  1424. startvarrecsize:=UnionSymtable.datasize;
  1425. { align the bitpacking to the next byte }
  1426. UnionSymtable.datasize:=startvarrecsize;
  1427. startvarrecalign:=UnionSymtable.fieldalignment;
  1428. startpadalign:=Unionsymtable.padalignment;
  1429. symtablestack.push(UnionSymtable);
  1430. repeat
  1431. repeat
  1432. pt:=comp_expr(true);
  1433. if not(pt.nodetype=ordconstn) then
  1434. Message(parser_e_illegal_expression);
  1435. if try_to_consume(_POINTPOINT) then
  1436. pt:=crangenode.create(pt,comp_expr(true));
  1437. pt.free;
  1438. if token=_COMMA then
  1439. consume(_COMMA)
  1440. else
  1441. break;
  1442. until false;
  1443. consume(_COLON);
  1444. { read the vars }
  1445. consume(_LKLAMMER);
  1446. inc(variantrecordlevel);
  1447. if token<>_RKLAMMER then
  1448. read_record_fields([vd_record]);
  1449. dec(variantrecordlevel);
  1450. consume(_RKLAMMER);
  1451. { calculates maximal variant size }
  1452. maxsize:=max(maxsize,unionsymtable.datasize);
  1453. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1454. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1455. { the items of the next variant are overlayed }
  1456. unionsymtable.datasize:=startvarrecsize;
  1457. unionsymtable.fieldalignment:=startvarrecalign;
  1458. unionsymtable.padalignment:=startpadalign;
  1459. if (token<>_END) and (token<>_RKLAMMER) then
  1460. consume(_SEMICOLON)
  1461. else
  1462. break;
  1463. until (token=_END) or (token=_RKLAMMER);
  1464. symtablestack.pop(UnionSymtable);
  1465. { at last set the record size to that of the biggest variant }
  1466. unionsymtable.datasize:=maxsize;
  1467. unionsymtable.fieldalignment:=maxalignment;
  1468. unionsymtable.addalignmentpadding;
  1469. {$if defined(powerpc) or defined(powerpc64)}
  1470. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1471. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1472. is_first_field and
  1473. (recst.usefieldalignment=C_alignment) and
  1474. (maxpadalign>recst.padalignment) then
  1475. recst.padalignment:=maxpadalign;
  1476. {$endif powerpc or powerpc64}
  1477. { Align the offset where the union symtable is added }
  1478. case recst.usefieldalignment of
  1479. { allow the unionsymtable to be aligned however it wants }
  1480. { (within the global min/max limits) }
  1481. 0, { default }
  1482. C_alignment:
  1483. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  1484. { 1 byte alignment if we are bitpacked }
  1485. bit_alignment:
  1486. usedalign:=1;
  1487. { otherwise alignment at the packrecords alignment of the }
  1488. { current record }
  1489. else
  1490. usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1491. end;
  1492. offset:=align(recst.datasize,usedalign);
  1493. recst.datasize:=offset+unionsymtable.datasize;
  1494. if unionsymtable.recordalignment>recst.fieldalignment then
  1495. recst.fieldalignment:=unionsymtable.recordalignment;
  1496. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  1497. uniondef.owner.deletedef(uniondef);
  1498. end;
  1499. { free the list }
  1500. sc.free;
  1501. {$ifdef powerpc}
  1502. is_first_field := false;
  1503. {$endif powerpc}
  1504. end;
  1505. end.