pdecvar.pas 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594
  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. {$ifdef i386}
  931. tmpaddr : int64;
  932. {$endif}
  933. begin
  934. abssym:=nil;
  935. { only allowed for one var }
  936. vs:=tabstractvarsym(sc[0]);
  937. if sc.count>1 then
  938. Message(parser_e_absolute_only_one_var);
  939. if vo_is_typed_const in vs.varoptions then
  940. Message(parser_e_initialized_not_for_external);
  941. { parse the rest }
  942. pt:=expr;
  943. { check allowed absolute types }
  944. if (pt.nodetype=stringconstn) or
  945. (is_constcharnode(pt)) then
  946. begin
  947. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  948. abssym.fileinfo:=vs.fileinfo;
  949. if pt.nodetype=stringconstn then
  950. abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
  951. else
  952. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  953. consume(token);
  954. abssym.abstyp:=toasm;
  955. end
  956. { address }
  957. else if is_constintnode(pt) then
  958. begin
  959. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  960. abssym.fileinfo:=vs.fileinfo;
  961. abssym.abstyp:=toaddr;
  962. {$ifndef cpu64bitaddr}
  963. { on 64 bit systems, abssym.addroffset is a qword and hence this
  964. test is useless (value is a 64 bit entity) and will always fail
  965. for positive values (since int64(high(abssym.addroffset))=-1
  966. }
  967. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  968. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  969. message(parser_e_range_check_error)
  970. else
  971. {$endif}
  972. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  973. {$ifdef i386}
  974. abssym.absseg:=false;
  975. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  976. try_to_consume(_COLON) then
  977. begin
  978. pt.free;
  979. pt:=expr;
  980. if is_constintnode(pt) then
  981. begin
  982. tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  983. if (tmpaddr<int64(low(abssym.addroffset))) or
  984. (tmpaddr>int64(high(abssym.addroffset))) then
  985. message(parser_e_range_check_error)
  986. else
  987. abssym.addroffset:=tmpaddr;
  988. abssym.absseg:=true;
  989. end
  990. else
  991. Message(type_e_ordinal_expr_expected);
  992. end;
  993. {$endif i386}
  994. end
  995. { variable }
  996. else
  997. begin
  998. { we have to be able to take the address of the absolute
  999. expression
  1000. }
  1001. valid_for_addr(pt,true);
  1002. { remove subscriptn before checking for loadn }
  1003. hp:=pt;
  1004. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1005. begin
  1006. { check for implicit dereferencing and reject it }
  1007. if (hp.nodetype in [subscriptn,vecn]) then
  1008. begin
  1009. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1010. break;
  1011. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1012. (pchar_var[5] is a pchar_2_string typeconv ->
  1013. the vecn only sees an array of char)
  1014. I don't know if all of these type conversions are
  1015. possible, but they're definitely all bad.
  1016. }
  1017. if (tunarynode(hp).left.nodetype=typeconvn) and
  1018. (ttypeconvnode(tunarynode(hp).left).convtype in
  1019. [tc_pchar_2_string,tc_pointer_2_array,
  1020. tc_intf_2_string,tc_intf_2_guid,
  1021. tc_dynarray_2_variant,tc_interface_2_variant,
  1022. tc_array_2_dynarray]) then
  1023. break;
  1024. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1025. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1026. break;
  1027. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1028. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1029. break;
  1030. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1031. break;
  1032. end;
  1033. hp:=tunarynode(hp).left;
  1034. end;
  1035. if (hp.nodetype=loadn) then
  1036. begin
  1037. { we should check the result type of loadn }
  1038. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
  1039. Message(parser_e_absolute_only_to_var_or_const);
  1040. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1041. abssym.fileinfo:=vs.fileinfo;
  1042. abssym.abstyp:=tovar;
  1043. abssym.ref:=node_to_propaccesslist(pt);
  1044. { if the sizes are different, can't be a regvar since you }
  1045. { can't be "absolute upper 8 bits of a register" (except }
  1046. { if its a record field of the same size of a record }
  1047. { regvar, but in that case pt.resultdef.size will have }
  1048. { the same size since it refers to the field and not to }
  1049. { the whole record -- which is why we use pt and not hp) }
  1050. { we can't take the size of an open array }
  1051. if is_open_array(pt.resultdef) or
  1052. (vs.vardef.size <> pt.resultdef.size) then
  1053. make_not_regable(pt,[ra_addr_regable]);
  1054. end
  1055. else
  1056. Message(parser_e_absolute_only_to_var_or_const);
  1057. end;
  1058. pt.free;
  1059. { replace old varsym with the new absolutevarsym }
  1060. if assigned(abssym) then
  1061. begin
  1062. st:=vs.owner;
  1063. vs.owner.Delete(vs);
  1064. st.insert(abssym);
  1065. sc[0]:=abssym;
  1066. end;
  1067. end;
  1068. var
  1069. sc : TFPObjectList;
  1070. vs : tabstractvarsym;
  1071. hdef : tdef;
  1072. i : longint;
  1073. semicoloneaten,
  1074. allowdefaultvalue,
  1075. hasdefaultvalue : boolean;
  1076. hintsymoptions : tsymoptions;
  1077. old_block_type : tblock_type;
  1078. begin
  1079. old_block_type:=block_type;
  1080. block_type:=bt_var;
  1081. { Force an expected ID error message }
  1082. if not (token in [_ID,_CASE,_END]) then
  1083. consume(_ID);
  1084. { read vars }
  1085. sc:=TFPObjectList.create(false);
  1086. while (token=_ID) do
  1087. begin
  1088. semicoloneaten:=false;
  1089. hasdefaultvalue:=false;
  1090. allowdefaultvalue:=true;
  1091. sc.clear;
  1092. repeat
  1093. if (token = _ID) then
  1094. begin
  1095. case symtablestack.top.symtabletype of
  1096. localsymtable :
  1097. vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  1098. staticsymtable,
  1099. globalsymtable :
  1100. begin
  1101. vs:=tstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
  1102. if vd_threadvar in options then
  1103. include(vs.varoptions,vo_is_thread_var);
  1104. end;
  1105. else
  1106. internalerror(200411064);
  1107. end;
  1108. sc.add(vs);
  1109. symtablestack.top.insert(vs);
  1110. end;
  1111. consume(_ID);
  1112. until not try_to_consume(_COMMA);
  1113. { read variable type def }
  1114. block_type:=bt_var_type;
  1115. consume(_COLON);
  1116. {$ifdef gpc_mode}
  1117. if (m_gpc in current_settings.modeswitches) and
  1118. (token=_ID) and
  1119. (orgpattern='__asmname__') then
  1120. read_gpc_name(sc);
  1121. {$endif}
  1122. read_anon_type(hdef,false);
  1123. for i:=0 to sc.count-1 do
  1124. begin
  1125. vs:=tabstractvarsym(sc[i]);
  1126. vs.vardef:=hdef;
  1127. end;
  1128. block_type:=bt_var;
  1129. { Process procvar directives }
  1130. if maybe_parse_proc_directives(hdef) then
  1131. semicoloneaten:=true;
  1132. { check for absolute }
  1133. if try_to_consume(_ABSOLUTE) then
  1134. begin
  1135. read_absolute(sc);
  1136. allowdefaultvalue:=false;
  1137. end;
  1138. { Check for EXTERNAL etc directives before a semicolon }
  1139. if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
  1140. begin
  1141. read_public_and_external_sc(sc);
  1142. allowdefaultvalue:=false;
  1143. semicoloneaten:=true;
  1144. end;
  1145. { try to parse the hint directives }
  1146. hintsymoptions:=[];
  1147. try_consume_hintdirective(hintsymoptions);
  1148. for i:=0 to sc.count-1 do
  1149. begin
  1150. vs:=tabstractvarsym(sc[i]);
  1151. vs.symoptions := vs.symoptions + hintsymoptions;
  1152. end;
  1153. { Handling of Delphi typed const = initialized vars }
  1154. if allowdefaultvalue and
  1155. (token=_EQUAL) and
  1156. not(m_tp7 in current_settings.modeswitches) and
  1157. (symtablestack.top.symtabletype<>parasymtable) then
  1158. begin
  1159. { Add calling convention for procvar }
  1160. if (hdef.typ=procvardef) and
  1161. (hdef.typesym=nil) then
  1162. handle_calling_convention(tprocvardef(hdef));
  1163. read_default_value(sc);
  1164. hasdefaultvalue:=true;
  1165. end
  1166. else
  1167. begin
  1168. if not(semicoloneaten) then
  1169. consume(_SEMICOLON);
  1170. end;
  1171. { Support calling convention for procvars after semicolon }
  1172. if not(hasdefaultvalue) and
  1173. (hdef.typ=procvardef) and
  1174. (hdef.typesym=nil) then
  1175. begin
  1176. { Parse procvar directives after ; }
  1177. maybe_parse_proc_directives(hdef);
  1178. { Add calling convention for procvar }
  1179. handle_calling_convention(tprocvardef(hdef));
  1180. { Handling of Delphi typed const = initialized vars }
  1181. if (token=_EQUAL) and
  1182. not(m_tp7 in current_settings.modeswitches) and
  1183. (symtablestack.top.symtabletype<>parasymtable) then
  1184. begin
  1185. read_default_value(sc);
  1186. hasdefaultvalue:=true;
  1187. end;
  1188. end;
  1189. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1190. if (
  1191. (
  1192. (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
  1193. (m_cvar_support in current_settings.modeswitches)
  1194. ) or
  1195. (
  1196. (m_mac in current_settings.modeswitches) and
  1197. (
  1198. (cs_external_var in current_settings.localswitches) or
  1199. (cs_externally_visible in current_settings.localswitches)
  1200. )
  1201. )
  1202. ) then
  1203. read_public_and_external_sc(sc);
  1204. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1205. for i:=0 to sc.count-1 do
  1206. begin
  1207. vs:=tabstractvarsym(sc[i]);
  1208. if (vs.typ=staticvarsym) and
  1209. not(vo_is_typed_const in vs.varoptions) and
  1210. not(vo_is_external in vs.varoptions) then
  1211. insertbssdata(tstaticvarsym(vs));
  1212. end;
  1213. end;
  1214. block_type:=old_block_type;
  1215. { free the list }
  1216. sc.free;
  1217. end;
  1218. procedure read_record_fields(options:Tvar_dec_options);
  1219. var
  1220. sc : TFPObjectList;
  1221. i : longint;
  1222. hs,sorg : string;
  1223. hdef,casetype : tdef;
  1224. { maxsize contains the max. size of a variant }
  1225. { startvarrec contains the start of the variant part of a record }
  1226. maxsize, startvarrecsize : longint;
  1227. usedalign,
  1228. maxalignment,startvarrecalign,
  1229. maxpadalign, startpadalign: shortint;
  1230. pt : tnode;
  1231. fieldvs : tfieldvarsym;
  1232. hstaticvs : tstaticvarsym;
  1233. vs : tabstractvarsym;
  1234. srsym : tsym;
  1235. srsymtable : TSymtable;
  1236. visibility : tvisibility;
  1237. recst : tabstractrecordsymtable;
  1238. unionsymtable : trecordsymtable;
  1239. offset : longint;
  1240. uniondef : trecorddef;
  1241. hintsymoptions : tsymoptions;
  1242. semicoloneaten: boolean;
  1243. {$if defined(powerpc) or defined(powerpc64)}
  1244. tempdef: tdef;
  1245. is_first_field: boolean;
  1246. {$endif powerpc or powerpc64}
  1247. sl : tpropaccesslist;
  1248. begin
  1249. recst:=tabstractrecordsymtable(symtablestack.top);
  1250. {$if defined(powerpc) or defined(powerpc64)}
  1251. is_first_field := true;
  1252. {$endif powerpc or powerpc64}
  1253. { Force an expected ID error message }
  1254. if not (token in [_ID,_CASE,_END]) then
  1255. consume(_ID);
  1256. { read vars }
  1257. sc:=TFPObjectList.create(false);
  1258. while (token=_ID) and
  1259. not((vd_object in options) and
  1260. (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
  1261. begin
  1262. visibility:=symtablestack.top.currentvisibility;
  1263. semicoloneaten:=false;
  1264. sc.clear;
  1265. repeat
  1266. sorg:=orgpattern;
  1267. if token=_ID then
  1268. begin
  1269. vs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1270. sc.add(vs);
  1271. recst.insert(vs);
  1272. end;
  1273. consume(_ID);
  1274. until not try_to_consume(_COMMA);
  1275. consume(_COLON);
  1276. { Don't search in the recordsymtable for types }
  1277. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1278. symtablestack.pop(recst);
  1279. read_anon_type(hdef,false);
  1280. if ([df_generic,df_specialization]*tdef(recst.defowner).defoptions=[]) then
  1281. symtablestack.push(recst);
  1282. { Process procvar directives }
  1283. if maybe_parse_proc_directives(hdef) then
  1284. semicoloneaten:=true;
  1285. {$if defined(powerpc) or defined(powerpc64)}
  1286. { from gcc/gcc/config/rs6000/rs6000.h:
  1287. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1288. /* Return the alignment of a struct based on the Macintosh PowerPC
  1289. alignment rules. In general the alignment of a struct is
  1290. determined by the greatest alignment of its elements. However, the
  1291. PowerPC rules cause the alignment of a struct to peg at word
  1292. alignment except when the first field has greater than word
  1293. (32-bit) alignment, in which case the alignment is determined by
  1294. the alignment of the first field. */
  1295. }
  1296. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1297. is_first_field and
  1298. (symtablestack.top.symtabletype=recordsymtable) and
  1299. (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
  1300. begin
  1301. tempdef:=hdef;
  1302. while tempdef.typ=arraydef do
  1303. tempdef:=tarraydef(tempdef).elementdef;
  1304. if tempdef.typ<>recorddef then
  1305. maxpadalign:=tempdef.alignment
  1306. else
  1307. maxpadalign:=trecorddef(tempdef).padalignment;
  1308. if (maxpadalign>4) and
  1309. (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
  1310. trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
  1311. is_first_field:=false;
  1312. end;
  1313. {$endif powerpc or powerpc64}
  1314. { types that use init/final are not allowed in variant parts, but
  1315. classes are allowed }
  1316. if (variantrecordlevel>0) and
  1317. (hdef.needs_inittable and not is_class(hdef)) then
  1318. Message(parser_e_cant_use_inittable_here);
  1319. { try to parse the hint directives }
  1320. hintsymoptions:=[];
  1321. try_consume_hintdirective(hintsymoptions);
  1322. { update variable type and hints }
  1323. for i:=0 to sc.count-1 do
  1324. begin
  1325. fieldvs:=tfieldvarsym(sc[i]);
  1326. fieldvs.vardef:=hdef;
  1327. { insert any additional hint directives }
  1328. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1329. end;
  1330. { Records and objects can't have default values }
  1331. { for a record there doesn't need to be a ; before the END or ) }
  1332. if not(token in [_END,_RKLAMMER]) and
  1333. not(semicoloneaten) then
  1334. consume(_SEMICOLON);
  1335. { Parse procvar directives after ; }
  1336. maybe_parse_proc_directives(hdef);
  1337. { Add calling convention for procvar }
  1338. if (hdef.typ=procvardef) and
  1339. (hdef.typesym=nil) then
  1340. handle_calling_convention(tprocvardef(hdef));
  1341. { Check for STATIC directive }
  1342. if (vd_object in options) and
  1343. (cs_static_keyword in current_settings.moduleswitches) and
  1344. (try_to_consume(_STATIC)) then
  1345. begin
  1346. { add static flag and staticvarsyms }
  1347. for i:=0 to sc.count-1 do
  1348. begin
  1349. fieldvs:=tfieldvarsym(sc[i]);
  1350. include(fieldvs.symoptions,sp_static);
  1351. { generate the symbol which reserves the space }
  1352. hstaticvs:=tstaticvarsym.create('$_static_'+lower(symtablestack.top.name^)+'_'+fieldvs.name,vs_value,hdef,[]);
  1353. recst.defowner.owner.insert(hstaticvs);
  1354. insertbssdata(hstaticvs);
  1355. { generate the symbol for the access }
  1356. sl:=tpropaccesslist.create;
  1357. sl.addsym(sl_load,hstaticvs);
  1358. recst.insert(tabsolutevarsym.create_ref('$'+lower(symtablestack.top.name^)+'_'+fieldvs.name,hdef,sl));
  1359. end;
  1360. consume(_SEMICOLON);
  1361. end;
  1362. if (visibility=vis_published) and
  1363. not(is_class(hdef)) then
  1364. begin
  1365. Message(parser_e_cant_publish_that);
  1366. visibility:=vis_public;
  1367. end;
  1368. if (visibility=vis_published) and
  1369. not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
  1370. not(m_delphi in current_settings.modeswitches) then
  1371. begin
  1372. Message(parser_e_only_publishable_classes_can_be_published);
  1373. visibility:=vis_public;
  1374. end;
  1375. { Generate field in the recordsymtable }
  1376. for i:=0 to sc.count-1 do
  1377. begin
  1378. fieldvs:=tfieldvarsym(sc[i]);
  1379. { static data fields are already inserted in the globalsymtable }
  1380. if not(sp_static in fieldvs.symoptions) then
  1381. recst.addfield(fieldvs,visibility);
  1382. end;
  1383. end;
  1384. { Check for Case }
  1385. if (vd_record in options) and
  1386. try_to_consume(_CASE) then
  1387. begin
  1388. maxsize:=0;
  1389. maxalignment:=0;
  1390. maxpadalign:=0;
  1391. { including a field declaration? }
  1392. fieldvs:=nil;
  1393. sorg:=orgpattern;
  1394. hs:=pattern;
  1395. searchsym(hs,srsym,srsymtable);
  1396. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1397. begin
  1398. consume(_ID);
  1399. consume(_COLON);
  1400. fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1401. symtablestack.top.insert(fieldvs);
  1402. end;
  1403. read_anon_type(casetype,true);
  1404. if assigned(fieldvs) then
  1405. begin
  1406. fieldvs.vardef:=casetype;
  1407. recst.addfield(fieldvs,recst.currentvisibility);
  1408. end;
  1409. if not(is_ordinal(casetype))
  1410. {$ifndef cpu64bitaddr}
  1411. or is_64bitint(casetype)
  1412. {$endif cpu64bitaddr}
  1413. then
  1414. Message(type_e_ordinal_expr_expected);
  1415. consume(_OF);
  1416. UnionSymtable:=trecordsymtable.create(current_settings.packrecords);
  1417. UnionDef:=trecorddef.create(unionsymtable);
  1418. uniondef.isunion:=true;
  1419. startvarrecsize:=UnionSymtable.datasize;
  1420. { align the bitpacking to the next byte }
  1421. UnionSymtable.datasize:=startvarrecsize;
  1422. startvarrecalign:=UnionSymtable.fieldalignment;
  1423. startpadalign:=Unionsymtable.padalignment;
  1424. symtablestack.push(UnionSymtable);
  1425. repeat
  1426. repeat
  1427. pt:=comp_expr(true);
  1428. if not(pt.nodetype=ordconstn) then
  1429. Message(parser_e_illegal_expression);
  1430. if try_to_consume(_POINTPOINT) then
  1431. pt:=crangenode.create(pt,comp_expr(true));
  1432. pt.free;
  1433. if token=_COMMA then
  1434. consume(_COMMA)
  1435. else
  1436. break;
  1437. until false;
  1438. consume(_COLON);
  1439. { read the vars }
  1440. consume(_LKLAMMER);
  1441. inc(variantrecordlevel);
  1442. if token<>_RKLAMMER then
  1443. read_record_fields([vd_record]);
  1444. dec(variantrecordlevel);
  1445. consume(_RKLAMMER);
  1446. { calculates maximal variant size }
  1447. maxsize:=max(maxsize,unionsymtable.datasize);
  1448. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1449. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1450. { the items of the next variant are overlayed }
  1451. unionsymtable.datasize:=startvarrecsize;
  1452. unionsymtable.fieldalignment:=startvarrecalign;
  1453. unionsymtable.padalignment:=startpadalign;
  1454. if (token<>_END) and (token<>_RKLAMMER) then
  1455. consume(_SEMICOLON)
  1456. else
  1457. break;
  1458. until (token=_END) or (token=_RKLAMMER);
  1459. symtablestack.pop(UnionSymtable);
  1460. { at last set the record size to that of the biggest variant }
  1461. unionsymtable.datasize:=maxsize;
  1462. unionsymtable.fieldalignment:=maxalignment;
  1463. unionsymtable.addalignmentpadding;
  1464. {$if defined(powerpc) or defined(powerpc64)}
  1465. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1466. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1467. is_first_field and
  1468. (recst.usefieldalignment=C_alignment) and
  1469. (maxpadalign>recst.padalignment) then
  1470. recst.padalignment:=maxpadalign;
  1471. {$endif powerpc or powerpc64}
  1472. { Align the offset where the union symtable is added }
  1473. case recst.usefieldalignment of
  1474. { allow the unionsymtable to be aligned however it wants }
  1475. { (within the global min/max limits) }
  1476. 0, { default }
  1477. C_alignment:
  1478. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  1479. { 1 byte alignment if we are bitpacked }
  1480. bit_alignment:
  1481. usedalign:=1;
  1482. { otherwise alignment at the packrecords alignment of the }
  1483. { current record }
  1484. else
  1485. usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1486. end;
  1487. offset:=align(recst.datasize,usedalign);
  1488. recst.datasize:=offset+unionsymtable.datasize;
  1489. if unionsymtable.recordalignment>recst.fieldalignment then
  1490. recst.fieldalignment:=unionsymtable.recordalignment;
  1491. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  1492. uniondef.owner.deletedef(uniondef);
  1493. end;
  1494. { free the list }
  1495. sc.free;
  1496. {$ifdef powerpc}
  1497. is_first_field := false;
  1498. {$endif powerpc}
  1499. end;
  1500. end.