pdecvar.pas 76 KB

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