pdecvar.pas 65 KB

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