pdecvar.pas 64 KB

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