pdecvar.pas 64 KB

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