pdecvar.pas 75 KB

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