pdecvar.pas 66 KB

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