pdecvar.pas 76 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. 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,[]);
  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. if cs_varpropsetter in current_settings.localswitches then
  568. p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults,cpo_ignorevarspez])
  569. else
  570. p.propaccesslist[palt_write].procdef:=Tprocsym(sym).Find_procdef_bypara(writeprocdef.paras,writeprocdef.returndef,[cpo_allowdefaults]);
  571. if not assigned(p.propaccesslist[palt_write].procdef) then
  572. Message(parser_e_ill_property_access_sym);
  573. end;
  574. fieldvarsym :
  575. begin
  576. if not assigned(def) then
  577. internalerror(200310072);
  578. if compare_defs(def,p.propdef,nothingn)>=te_equal then
  579. begin
  580. { property parameters are allowed if this is
  581. an indexed property, because the index is then
  582. the parameter.
  583. Note: In the help of Kylix it is written
  584. that it isn't allowed, but the compiler accepts it (PFV) }
  585. if (ppo_hasparameters in p.propoptions) or
  586. ((sp_static in p.symoptions) <> (sp_static in sym.symoptions)) then
  587. Message(parser_e_ill_property_access_sym);
  588. end
  589. else
  590. IncompatibleTypes(def,p.propdef);
  591. end;
  592. else
  593. Message(parser_e_ill_property_access_sym);
  594. end;
  595. end;
  596. end;
  597. end
  598. else
  599. parse_dispinterface(p,readprocdef,writeprocdef,paranr);
  600. { stored is not allowed for dispinterfaces, records or class properties }
  601. if assigned(astruct) and not(is_dispinterface(astruct) or is_record(astruct)) and not is_classproperty then
  602. begin
  603. { ppo_stored is default on for not overridden properties }
  604. if not assigned(p.overriddenpropsym) then
  605. include(p.propoptions,ppo_stored);
  606. if try_to_consume(_STORED) then
  607. begin
  608. include(p.propoptions,ppo_stored);
  609. p.propaccesslist[palt_stored].clear;
  610. case token of
  611. _ID:
  612. begin
  613. { in the case that idtoken=_DEFAULT }
  614. { we have to do nothing except }
  615. { setting ppo_stored, it's the same }
  616. { as stored true }
  617. if idtoken<>_DEFAULT then
  618. begin
  619. { parse_symlist cannot deal with constsyms, and
  620. we also don't want to put constsyms in symlists
  621. since they have to be evaluated immediately rather
  622. than each time the property is accessed
  623. The proper fix would be to always create a parse tree
  624. and then convert that one, if appropriate, to a symlist.
  625. Currently, we e.g. don't support any constant expressions
  626. yet either here, while Delphi does.
  627. }
  628. { make sure we don't let constants mask class fields/
  629. methods
  630. }
  631. if (not assigned(astruct) or
  632. (search_struct_member(astruct,pattern)=nil)) and
  633. searchsym(pattern,sym,srsymtable) and
  634. (sym.typ = constsym) then
  635. begin
  636. addsymref(sym);
  637. if not is_boolean(tconstsym(sym).constdef) then
  638. Message(parser_e_stored_property_must_be_boolean)
  639. else if (tconstsym(sym).value.valueord=0) then
  640. { same as for _FALSE }
  641. exclude(p.propoptions,ppo_stored)
  642. else
  643. { same as for _TRUE }
  644. p.default:=longint($80000000);
  645. consume(_ID);
  646. end
  647. else if parse_symlist(p.propaccesslist[palt_stored],def) then
  648. begin
  649. sym:=p.propaccesslist[palt_stored].firstsym^.sym;
  650. case sym.typ of
  651. procsym :
  652. begin
  653. { Create a temporary procvardef to handle parameters }
  654. storedprocdef:=tprocvardef.create(normal_function_level);
  655. include(storedprocdef.procoptions,po_methodpointer);
  656. { Return type must be boolean }
  657. storedprocdef.returndef:=pasbool8type;
  658. { Add index parameter if needed }
  659. if ppo_indexed in p.propoptions then
  660. begin
  661. hparavs:=tparavarsym.create('$index',10,vs_value,p.indexdef,[]);
  662. storedprocdef.parast.insert(hparavs);
  663. end;
  664. { Insert hidden parameters }
  665. handle_calling_convention(storedprocdef);
  666. p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
  667. if not assigned(p.propaccesslist[palt_stored].procdef) then
  668. message(parser_e_ill_property_storage_sym);
  669. { Not needed anymore }
  670. storedprocdef.owner.deletedef(storedprocdef);
  671. end;
  672. fieldvarsym :
  673. begin
  674. if not assigned(def) then
  675. internalerror(200310073);
  676. if (ppo_hasparameters in p.propoptions) or
  677. not(is_boolean(def)) then
  678. Message(parser_e_stored_property_must_be_boolean);
  679. end;
  680. else
  681. Message(parser_e_ill_property_access_sym);
  682. end;
  683. end;
  684. end;
  685. end;
  686. _FALSE:
  687. begin
  688. consume(_FALSE);
  689. exclude(p.propoptions,ppo_stored);
  690. end;
  691. _TRUE:
  692. begin
  693. p.default:=longint($80000000);
  694. consume(_TRUE);
  695. end;
  696. end;
  697. end;
  698. end;
  699. if not is_record(astruct) and try_to_consume(_DEFAULT) then
  700. begin
  701. if not allow_default_property(p) then
  702. begin
  703. Message(parser_e_property_cant_have_a_default_value);
  704. { Error recovery }
  705. pt:=comp_expr(true,false);
  706. pt.free;
  707. end
  708. else
  709. begin
  710. { Get the result of the default, the firstpass is
  711. needed to support values like -1 }
  712. pt:=comp_expr(true,false);
  713. if (p.propdef.typ=setdef) and
  714. (pt.nodetype=arrayconstructorn) then
  715. begin
  716. arrayconstructor_to_set(pt);
  717. do_typecheckpass(pt);
  718. end;
  719. inserttypeconv(pt,p.propdef);
  720. if not(is_constnode(pt)) then
  721. Message(parser_e_property_default_value_must_const);
  722. { Set default value }
  723. case pt.nodetype of
  724. setconstn :
  725. p.default:=plongint(tsetconstnode(pt).value_set)^;
  726. ordconstn :
  727. if (Tordconstnode(pt).value<int64(low(longint))) or
  728. (Tordconstnode(pt).value>int64(high(cardinal))) then
  729. message(parser_e_range_check_error)
  730. else
  731. p.default:=longint(tordconstnode(pt).value.svalue);
  732. niln :
  733. p.default:=0;
  734. realconstn:
  735. p.default:=longint(single(trealconstnode(pt).value_real));
  736. end;
  737. pt.free;
  738. end;
  739. end
  740. else if not is_record(astruct) and try_to_consume(_NODEFAULT) then
  741. begin
  742. p.default:=longint($80000000);
  743. end;
  744. (*
  745. else {if allow_default_property(p) then
  746. begin
  747. p.default:=longint($80000000);
  748. end;
  749. *)
  750. { Parse possible "implements" keyword }
  751. if not is_record(astruct) and try_to_consume(_IMPLEMENTS) then
  752. repeat
  753. single_type(def,[]);
  754. if not(is_interface(def)) then
  755. message(parser_e_class_implements_must_be_interface);
  756. if is_interface(p.propdef) then
  757. begin
  758. { an interface type may delegate itself or one of its ancestors }
  759. if not p.propdef.is_related(def) then
  760. begin
  761. message2(parser_e_implements_must_have_correct_type,def.typename,p.propdef.typename);
  762. exit;
  763. end;
  764. end
  765. else if is_class(p.propdef) then
  766. begin
  767. ImplIntf:=tobjectdef(p.propdef).find_implemented_interface(tobjectdef(def));
  768. if assigned(ImplIntf) then
  769. begin
  770. if compare_defs(ImplIntf.IntfDef,def,nothingn)<te_equal then
  771. begin
  772. message2(parser_e_implements_must_have_correct_type,ImplIntf.IntfDef.typename,def.typename);
  773. exit;
  774. end;
  775. end
  776. else
  777. begin
  778. message2(parser_e_class_doesnt_implement_interface,p.propdef.typename,def.typename);
  779. exit;
  780. end;
  781. end
  782. else
  783. begin
  784. message(parser_e_implements_must_be_class_or_interface);
  785. exit;
  786. end;
  787. if not assigned(p.propaccesslist[palt_read].firstsym) then
  788. begin
  789. message(parser_e_implements_must_read_specifier);
  790. exit;
  791. end;
  792. if assigned(p.propaccesslist[palt_read].procdef) and
  793. (tprocdef(p.propaccesslist[palt_read].procdef).proccalloption<>pocall_default) then
  794. message(parser_e_implements_getter_not_default_cc);
  795. if assigned(p.propaccesslist[palt_write].firstsym) then
  796. begin
  797. message(parser_e_implements_must_not_have_write_specifier);
  798. exit;
  799. end;
  800. if assigned(p.propaccesslist[palt_stored].firstsym) then
  801. begin
  802. message(parser_e_implements_must_not_have_stored_specifier);
  803. exit;
  804. end;
  805. found:=false;
  806. for i:=0 to tobjectdef(astruct).ImplementedInterfaces.Count-1 do
  807. begin
  808. ImplIntf:=TImplementedInterface(tobjectdef(astruct).ImplementedInterfaces[i]);
  809. if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
  810. begin
  811. found:=true;
  812. break;
  813. end;
  814. end;
  815. if found then
  816. begin
  817. { An interface may not be delegated by more than one property,
  818. it also may not have method mappings. }
  819. if Assigned(ImplIntf.ImplementsGetter) then
  820. message1(parser_e_duplicate_implements_clause,ImplIntf.IntfDef.typename);
  821. if Assigned(ImplIntf.NameMappings) then
  822. message2(parser_e_mapping_no_implements,ImplIntf.IntfDef.typename,astruct.objrealname^);
  823. ImplIntf.ImplementsGetter:=p;
  824. ImplIntf.VtblImplIntf:=ImplIntf;
  825. case p.propaccesslist[palt_read].firstsym^.sym.typ of
  826. procsym :
  827. begin
  828. if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) and
  829. not is_objectpascal_helper(tprocdef(p.propaccesslist[palt_read].procdef).struct) then
  830. ImplIntf.IType:=etVirtualMethodResult
  831. else
  832. ImplIntf.IType:=etStaticMethodResult;
  833. end;
  834. fieldvarsym :
  835. begin
  836. ImplIntf.IType:=etFieldValue;
  837. { this must be done more sophisticated, here is also probably the wrong place }
  838. ImplIntf.IOffset:=tfieldvarsym(p.propaccesslist[palt_read].firstsym^.sym).fieldoffset;
  839. end
  840. else
  841. internalerror(200802161);
  842. end;
  843. if not is_interface(p.propdef) then
  844. case ImplIntf.IType of
  845. etVirtualMethodResult: ImplIntf.IType := etVirtualMethodClass;
  846. etStaticMethodResult: ImplIntf.IType := etStaticMethodClass;
  847. etFieldValue: ImplIntf.IType := etFieldValueClass;
  848. else
  849. internalerror(200912101);
  850. end;
  851. end
  852. else
  853. message1(parser_e_implements_uses_non_implemented_interface,def.typename);
  854. until not try_to_consume(_COMMA);
  855. { remove unneeded procdefs }
  856. if readprocdef.proctypeoption<>potype_propgetter then
  857. readprocdef.owner.deletedef(readprocdef);
  858. if writeprocdef.proctypeoption<>potype_propsetter then
  859. writeprocdef.owner.deletedef(writeprocdef);
  860. result:=p;
  861. end;
  862. function maybe_parse_proc_directives(def:tdef):boolean;
  863. var
  864. newtype : ttypesym;
  865. begin
  866. result:=false;
  867. { Process procvar directives before = and ; }
  868. if (def.typ=procvardef) and
  869. (def.typesym=nil) and
  870. check_proc_directive(true) then
  871. begin
  872. newtype:=ttypesym.create('unnamed',def);
  873. parse_var_proc_directives(tsym(newtype));
  874. newtype.typedef:=nil;
  875. def.typesym:=nil;
  876. newtype.free;
  877. result:=true;
  878. end;
  879. end;
  880. const
  881. variantrecordlevel : longint = 0;
  882. procedure read_public_and_external_sc(sc:TFPObjectList);
  883. var
  884. vs: tabstractvarsym;
  885. begin
  886. { only allowed for one var }
  887. vs:=tabstractvarsym(sc[0]);
  888. if sc.count>1 then
  889. Message(parser_e_absolute_only_one_var);
  890. read_public_and_external(vs);
  891. end;
  892. procedure read_public_and_external(vs: tabstractvarsym);
  893. var
  894. is_dll,
  895. is_cdecl,
  896. is_external_var,
  897. is_weak_external,
  898. is_public_var : boolean;
  899. dll_name,section_name,
  900. C_name,mangledname : string;
  901. begin
  902. { only allowed for one var }
  903. { only allow external and public on global symbols }
  904. if vs.typ<>staticvarsym then
  905. begin
  906. Message(parser_e_no_local_var_external);
  907. exit;
  908. end;
  909. { defaults }
  910. is_dll:=false;
  911. is_cdecl:=false;
  912. is_external_var:=false;
  913. is_public_var:=false;
  914. section_name := '';
  915. C_name:=vs.realname;
  916. { macpas specific handling due to some switches}
  917. if (m_mac in current_settings.modeswitches) then
  918. begin
  919. if (cs_external_var in current_settings.localswitches) then
  920. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  921. is_cdecl:=true;
  922. is_external_var:=true;
  923. end
  924. else if (cs_externally_visible in current_settings.localswitches) then
  925. begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
  926. is_cdecl:=true;
  927. is_public_var:=true;
  928. end;
  929. end;
  930. { cdecl }
  931. if try_to_consume(_CVAR) then
  932. begin
  933. consume(_SEMICOLON);
  934. is_cdecl:=true;
  935. end;
  936. { external }
  937. is_weak_external:=try_to_consume(_WEAKEXTERNAL);
  938. if is_weak_external or
  939. try_to_consume(_EXTERNAL) then
  940. begin
  941. is_external_var:=true;
  942. if (idtoken<>_NAME) and (token<>_SEMICOLON) then
  943. begin
  944. is_dll:=true;
  945. dll_name:=get_stringconst;
  946. if ExtractFileExt(dll_name)='' then
  947. dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
  948. end;
  949. if not(is_cdecl) and try_to_consume(_NAME) then
  950. C_name:=get_stringconst;
  951. consume(_SEMICOLON);
  952. end;
  953. { export or public }
  954. if idtoken in [_EXPORT,_PUBLIC] then
  955. begin
  956. consume(_ID);
  957. if is_external_var then
  958. Message(parser_e_not_external_and_export)
  959. else
  960. is_public_var:=true;
  961. if try_to_consume(_NAME) then
  962. C_name:=get_stringconst;
  963. if (target_info.system in systems_allow_section_no_semicolon) and
  964. (vs.typ=staticvarsym) and
  965. try_to_consume (_SECTION) then
  966. section_name:=get_stringconst;
  967. consume(_SEMICOLON);
  968. end;
  969. { Windows uses an indirect reference using import tables }
  970. if is_dll and
  971. (target_info.system in systems_all_windows) then
  972. include(vs.varoptions,vo_is_dll_var);
  973. { This can only happen if vs.typ=staticvarsym }
  974. if section_name<>'' then
  975. begin
  976. tstaticvarsym(vs).section:=section_name;
  977. include(vs.varoptions,vo_has_section);
  978. end;
  979. { Add C _ prefix }
  980. if is_cdecl or
  981. (
  982. is_dll and
  983. (target_info.system in systems_darwin)
  984. ) then
  985. C_Name := target_info.Cprefix+C_Name;
  986. if is_public_var then
  987. begin
  988. include(vs.varoptions,vo_is_public);
  989. vs.varregable := vr_none;
  990. { mark as referenced }
  991. inc(vs.refs);
  992. end;
  993. mangledname:=C_name;
  994. { now we can insert it in the import lib if its a dll, or
  995. add it to the externals }
  996. if is_external_var then
  997. begin
  998. if vo_is_typed_const in vs.varoptions then
  999. Message(parser_e_initialized_not_for_external);
  1000. include(vs.varoptions,vo_is_external);
  1001. if (is_weak_external) then
  1002. begin
  1003. if not(target_info.system in systems_weak_linking) then
  1004. message(parser_e_weak_external_not_supported);
  1005. include(vs.varoptions,vo_is_weak_external);
  1006. end;
  1007. vs.varregable := vr_none;
  1008. if is_dll then
  1009. begin
  1010. if target_info.system in (systems_all_windows + systems_nativent +
  1011. [system_i386_emx, system_i386_os2]) then
  1012. mangledname:=make_dllmangledname(dll_name,C_name,0,pocall_none);
  1013. current_module.AddExternalImport(dll_name,C_Name,mangledname,0,true,false);
  1014. end
  1015. else
  1016. if tf_has_dllscanner in target_info.flags then
  1017. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  1018. end;
  1019. { Set the assembler name }
  1020. tstaticvarsym(vs).set_mangledname(mangledname);
  1021. end;
  1022. procedure try_consume_sectiondirective(var asection: ansistring);
  1023. begin
  1024. if idtoken=_SECTION then
  1025. begin
  1026. consume(_ID);
  1027. asection:=get_stringconst;
  1028. consume(_SEMICOLON);
  1029. end;
  1030. end;
  1031. procedure read_var_decls(options:Tvar_dec_options);
  1032. procedure read_default_value(sc : TFPObjectList);
  1033. var
  1034. vs : tabstractnormalvarsym;
  1035. tcsym : tstaticvarsym;
  1036. begin
  1037. vs:=tabstractnormalvarsym(sc[0]);
  1038. if sc.count>1 then
  1039. Message(parser_e_initialized_only_one_var);
  1040. if vo_is_thread_var in vs.varoptions then
  1041. Message(parser_e_initialized_not_for_threadvar);
  1042. consume(_EQ);
  1043. case vs.typ of
  1044. localvarsym :
  1045. begin
  1046. tcsym:=tstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[]);
  1047. include(tcsym.symoptions,sp_internal);
  1048. vs.defaultconstsym:=tcsym;
  1049. symtablestack.top.insert(tcsym);
  1050. read_typed_const(current_asmdata.asmlists[al_typedconsts],tcsym,false);
  1051. end;
  1052. staticvarsym :
  1053. begin
  1054. read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs),false);
  1055. end;
  1056. else
  1057. internalerror(200611051);
  1058. end;
  1059. vs.varstate:=vs_initialised;
  1060. end;
  1061. {$ifdef gpc_mode}
  1062. procedure read_gpc_name(sc : TFPObjectList);
  1063. var
  1064. vs : tabstractnormalvarsym;
  1065. C_Name : string;
  1066. begin
  1067. consume(_ID);
  1068. C_Name:=get_stringconst;
  1069. vs:=tabstractnormalvarsym(sc[0]);
  1070. if sc.count>1 then
  1071. Message(parser_e_absolute_only_one_var);
  1072. if vs.typ=staticvarsym then
  1073. begin
  1074. tstaticvarsym(vs).set_mangledname(C_Name);
  1075. include(vs.varoptions,vo_is_external);
  1076. end
  1077. else
  1078. Message(parser_e_no_local_var_external);
  1079. end;
  1080. {$endif}
  1081. procedure read_absolute(sc : TFPObjectList);
  1082. var
  1083. vs : tabstractvarsym;
  1084. abssym : tabsolutevarsym;
  1085. pt,hp : tnode;
  1086. st : tsymtable;
  1087. {$ifdef i386}
  1088. tmpaddr : int64;
  1089. {$endif}
  1090. begin
  1091. abssym:=nil;
  1092. { only allowed for one var }
  1093. vs:=tabstractvarsym(sc[0]);
  1094. if sc.count>1 then
  1095. Message(parser_e_absolute_only_one_var);
  1096. if vo_is_typed_const in vs.varoptions then
  1097. Message(parser_e_initialized_not_for_external);
  1098. { parse the rest }
  1099. pt:=expr(true);
  1100. { check allowed absolute types }
  1101. if (pt.nodetype=stringconstn) or
  1102. (is_constcharnode(pt)) then
  1103. begin
  1104. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1105. abssym.fileinfo:=vs.fileinfo;
  1106. if pt.nodetype=stringconstn then
  1107. abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
  1108. else
  1109. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  1110. consume(token);
  1111. abssym.abstyp:=toasm;
  1112. end
  1113. { address }
  1114. else if is_constintnode(pt) then
  1115. begin
  1116. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1117. abssym.fileinfo:=vs.fileinfo;
  1118. abssym.abstyp:=toaddr;
  1119. {$ifndef cpu64bitaddr}
  1120. { on 64 bit systems, abssym.addroffset is a qword and hence this
  1121. test is useless (value is a 64 bit entity) and will always fail
  1122. for positive values (since int64(high(abssym.addroffset))=-1
  1123. }
  1124. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  1125. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  1126. message(parser_e_range_check_error)
  1127. else
  1128. {$endif}
  1129. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  1130. {$ifdef i386}
  1131. abssym.absseg:=false;
  1132. if (target_info.system in [system_i386_go32v2,system_i386_watcom]) and
  1133. try_to_consume(_COLON) then
  1134. begin
  1135. pt.free;
  1136. pt:=expr(true);
  1137. if is_constintnode(pt) then
  1138. begin
  1139. tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  1140. if (tmpaddr<int64(low(abssym.addroffset))) or
  1141. (tmpaddr>int64(high(abssym.addroffset))) then
  1142. message(parser_e_range_check_error)
  1143. else
  1144. abssym.addroffset:=tmpaddr;
  1145. abssym.absseg:=true;
  1146. end
  1147. else
  1148. Message(type_e_ordinal_expr_expected);
  1149. end;
  1150. {$endif i386}
  1151. end
  1152. { variable }
  1153. else
  1154. begin
  1155. { we have to be able to take the address of the absolute
  1156. expression
  1157. }
  1158. valid_for_addr(pt,true);
  1159. { remove subscriptn before checking for loadn }
  1160. hp:=pt;
  1161. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1162. begin
  1163. { check for implicit dereferencing and reject it }
  1164. if (hp.nodetype in [subscriptn,vecn]) then
  1165. begin
  1166. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1167. break;
  1168. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1169. (pchar_var[5] is a pchar_2_string typeconv ->
  1170. the vecn only sees an array of char)
  1171. I don't know if all of these type conversions are
  1172. possible, but they're definitely all bad.
  1173. }
  1174. if (tunarynode(hp).left.nodetype=typeconvn) and
  1175. (ttypeconvnode(tunarynode(hp).left).convtype in
  1176. [tc_pchar_2_string,tc_pointer_2_array,
  1177. tc_intf_2_string,tc_intf_2_guid,
  1178. tc_dynarray_2_variant,tc_interface_2_variant,
  1179. tc_array_2_dynarray]) then
  1180. break;
  1181. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1182. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1183. break;
  1184. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1185. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1186. break;
  1187. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1188. break;
  1189. end;
  1190. hp:=tunarynode(hp).left;
  1191. end;
  1192. if (hp.nodetype=loadn) then
  1193. begin
  1194. { we should check the result type of loadn }
  1195. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
  1196. Message(parser_e_absolute_only_to_var_or_const);
  1197. abssym:=tabsolutevarsym.create(vs.realname,vs.vardef);
  1198. abssym.fileinfo:=vs.fileinfo;
  1199. abssym.abstyp:=tovar;
  1200. abssym.ref:=node_to_propaccesslist(pt);
  1201. { if the sizes are different, can't be a regvar since you }
  1202. { can't be "absolute upper 8 bits of a register" (except }
  1203. { if its a record field of the same size of a record }
  1204. { regvar, but in that case pt.resultdef.size will have }
  1205. { the same size since it refers to the field and not to }
  1206. { the whole record -- which is why we use pt and not hp) }
  1207. { we can't take the size of an open array }
  1208. if is_open_array(pt.resultdef) or
  1209. (vs.vardef.size <> pt.resultdef.size) then
  1210. make_not_regable(pt,[ra_addr_regable]);
  1211. end
  1212. else
  1213. Message(parser_e_absolute_only_to_var_or_const);
  1214. end;
  1215. pt.free;
  1216. { replace old varsym with the new absolutevarsym }
  1217. if assigned(abssym) then
  1218. begin
  1219. st:=vs.owner;
  1220. vs.owner.Delete(vs);
  1221. st.insert(abssym);
  1222. sc[0]:=abssym;
  1223. end;
  1224. end;
  1225. var
  1226. sc : TFPObjectList;
  1227. vs : tabstractvarsym;
  1228. hdef : tdef;
  1229. i : longint;
  1230. semicoloneaten,
  1231. allowdefaultvalue,
  1232. hasdefaultvalue : boolean;
  1233. hintsymoptions : tsymoptions;
  1234. deprecatedmsg : pshortstring;
  1235. old_block_type : tblock_type;
  1236. sectionname : ansistring;
  1237. begin
  1238. old_block_type:=block_type;
  1239. block_type:=bt_var;
  1240. { Force an expected ID error message }
  1241. if not (token in [_ID,_CASE,_END]) then
  1242. consume(_ID);
  1243. { read vars }
  1244. sc:=TFPObjectList.create(false);
  1245. while (token=_ID) do
  1246. begin
  1247. semicoloneaten:=false;
  1248. hasdefaultvalue:=false;
  1249. allowdefaultvalue:=true;
  1250. sc.clear;
  1251. repeat
  1252. if (token = _ID) then
  1253. begin
  1254. case symtablestack.top.symtabletype of
  1255. localsymtable :
  1256. vs:=tlocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  1257. staticsymtable,
  1258. globalsymtable :
  1259. begin
  1260. vs:=tstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
  1261. if vd_threadvar in options then
  1262. include(vs.varoptions,vo_is_thread_var);
  1263. end;
  1264. else
  1265. internalerror(200411064);
  1266. end;
  1267. sc.add(vs);
  1268. symtablestack.top.insert(vs);
  1269. end;
  1270. consume(_ID);
  1271. until not try_to_consume(_COMMA);
  1272. { read variable type def }
  1273. block_type:=bt_var_type;
  1274. consume(_COLON);
  1275. {$ifdef gpc_mode}
  1276. if (m_gpc in current_settings.modeswitches) and
  1277. (token=_ID) and
  1278. (orgpattern='__asmname__') then
  1279. read_gpc_name(sc);
  1280. {$endif}
  1281. read_anon_type(hdef,false);
  1282. for i:=0 to sc.count-1 do
  1283. begin
  1284. vs:=tabstractvarsym(sc[i]);
  1285. vs.vardef:=hdef;
  1286. end;
  1287. block_type:=bt_var;
  1288. { Process procvar directives }
  1289. if maybe_parse_proc_directives(hdef) then
  1290. semicoloneaten:=true;
  1291. { check for absolute }
  1292. if try_to_consume(_ABSOLUTE) then
  1293. begin
  1294. read_absolute(sc);
  1295. allowdefaultvalue:=false;
  1296. end;
  1297. { Check for EXTERNAL etc directives before a semicolon }
  1298. if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
  1299. begin
  1300. read_public_and_external_sc(sc);
  1301. allowdefaultvalue:=false;
  1302. semicoloneaten:=true;
  1303. end;
  1304. { try to parse the hint directives }
  1305. hintsymoptions:=[];
  1306. deprecatedmsg:=nil;
  1307. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1308. for i:=0 to sc.count-1 do
  1309. begin
  1310. vs:=tabstractvarsym(sc[i]);
  1311. vs.symoptions := vs.symoptions + hintsymoptions;
  1312. if deprecatedmsg<>nil then
  1313. vs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1314. end;
  1315. stringdispose(deprecatedmsg);
  1316. { Handling of Delphi typed const = initialized vars }
  1317. if allowdefaultvalue and
  1318. (token=_EQ) and
  1319. not(m_tp7 in current_settings.modeswitches) and
  1320. (symtablestack.top.symtabletype<>parasymtable) then
  1321. begin
  1322. { Add calling convention for procvar }
  1323. if (hdef.typ=procvardef) and
  1324. (hdef.typesym=nil) then
  1325. handle_calling_convention(tprocvardef(hdef));
  1326. read_default_value(sc);
  1327. hasdefaultvalue:=true;
  1328. end
  1329. else
  1330. begin
  1331. if not(semicoloneaten) then
  1332. consume(_SEMICOLON);
  1333. end;
  1334. { Support calling convention for procvars after semicolon }
  1335. if not(hasdefaultvalue) and
  1336. (hdef.typ=procvardef) and
  1337. (hdef.typesym=nil) then
  1338. begin
  1339. { Parse procvar directives after ; }
  1340. maybe_parse_proc_directives(hdef);
  1341. { Add calling convention for procvar }
  1342. handle_calling_convention(tprocvardef(hdef));
  1343. { Handling of Delphi typed const = initialized vars }
  1344. if (token=_EQ) and
  1345. not(m_tp7 in current_settings.modeswitches) and
  1346. (symtablestack.top.symtabletype<>parasymtable) then
  1347. begin
  1348. read_default_value(sc);
  1349. hasdefaultvalue:=true;
  1350. end;
  1351. end;
  1352. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1353. if (
  1354. (
  1355. (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
  1356. (m_cvar_support in current_settings.modeswitches)
  1357. ) or
  1358. (
  1359. (m_mac in current_settings.modeswitches) and
  1360. (
  1361. (cs_external_var in current_settings.localswitches) or
  1362. (cs_externally_visible in current_settings.localswitches)
  1363. )
  1364. )
  1365. ) then
  1366. read_public_and_external_sc(sc);
  1367. { try to parse a section directive }
  1368. if (target_info.system in systems_allow_section) and
  1369. (symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) and
  1370. (idtoken=_SECTION) then
  1371. begin
  1372. try_consume_sectiondirective(sectionname);
  1373. if sectionname<>'' then
  1374. begin
  1375. for i:=0 to sc.count-1 do
  1376. begin
  1377. vs:=tabstractvarsym(sc[i]);
  1378. if (vs.varoptions *[vo_is_external,vo_is_weak_external])<>[] then
  1379. Message(parser_e_externals_no_section);
  1380. if vs.typ<>staticvarsym then
  1381. Message(parser_e_section_no_locals);
  1382. tstaticvarsym(vs).section:=sectionname;
  1383. include(vs.varoptions, vo_has_section);
  1384. end;
  1385. end;
  1386. end;
  1387. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1388. for i:=0 to sc.count-1 do
  1389. begin
  1390. vs:=tabstractvarsym(sc[i]);
  1391. if (vs.typ=staticvarsym) and
  1392. not(vo_is_typed_const in vs.varoptions) and
  1393. not(vo_is_external in vs.varoptions) then
  1394. insertbssdata(tstaticvarsym(vs));
  1395. end;
  1396. end;
  1397. block_type:=old_block_type;
  1398. { free the list }
  1399. sc.free;
  1400. end;
  1401. procedure read_record_fields(options:Tvar_dec_options);
  1402. var
  1403. sc : TFPObjectList;
  1404. i : longint;
  1405. hs,sorg,static_name : string;
  1406. hdef,casetype : tdef;
  1407. { maxsize contains the max. size of a variant }
  1408. { startvarrec contains the start of the variant part of a record }
  1409. maxsize, startvarrecsize : longint;
  1410. usedalign,
  1411. maxalignment,startvarrecalign,
  1412. maxpadalign, startpadalign: shortint;
  1413. pt : tnode;
  1414. fieldvs : tfieldvarsym;
  1415. hstaticvs : tstaticvarsym;
  1416. vs : tabstractvarsym;
  1417. srsym : tsym;
  1418. srsymtable : TSymtable;
  1419. visibility : tvisibility;
  1420. recst : tabstractrecordsymtable;
  1421. recstlist : tfpobjectlist;
  1422. unionsymtable : trecordsymtable;
  1423. offset : longint;
  1424. uniondef : trecorddef;
  1425. hintsymoptions : tsymoptions;
  1426. deprecatedmsg : pshortstring;
  1427. semicoloneaten,
  1428. removeclassoption: boolean;
  1429. {$if defined(powerpc) or defined(powerpc64)}
  1430. tempdef: tdef;
  1431. is_first_type: boolean;
  1432. {$endif powerpc or powerpc64}
  1433. sl: tpropaccesslist;
  1434. old_block_type: tblock_type;
  1435. begin
  1436. old_block_type:=block_type;
  1437. block_type:=bt_var;
  1438. recst:=tabstractrecordsymtable(symtablestack.top);
  1439. {$if defined(powerpc) or defined(powerpc64)}
  1440. is_first_type:=true;
  1441. {$endif powerpc or powerpc64}
  1442. { Force an expected ID error message }
  1443. if not (token in [_ID,_CASE,_END]) then
  1444. consume(_ID);
  1445. { read vars }
  1446. sc:=TFPObjectList.create(false);
  1447. recstlist:=TFPObjectList.create(false);
  1448. removeclassoption:=false;
  1449. while (token=_ID) and
  1450. not(((vd_object in options) or
  1451. ((vd_record in options) and (m_advanced_records in current_settings.modeswitches))) and
  1452. (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
  1453. begin
  1454. visibility:=symtablestack.top.currentvisibility;
  1455. semicoloneaten:=false;
  1456. sc.clear;
  1457. repeat
  1458. sorg:=orgpattern;
  1459. if token=_ID then
  1460. begin
  1461. vs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1462. sc.add(vs);
  1463. recst.insert(vs);
  1464. end;
  1465. consume(_ID);
  1466. until not try_to_consume(_COMMA);
  1467. if m_delphi in current_settings.modeswitches then
  1468. block_type:=bt_var_type
  1469. else
  1470. block_type:=old_block_type;
  1471. consume(_COLON);
  1472. { Don't search for types where they can't be:
  1473. types can be only in objects, classes and records.
  1474. This just speedup the search a bit. }
  1475. recstlist.count:=0;
  1476. if not is_class_or_object(tdef(recst.defowner)) and
  1477. not is_record(tdef(recst.defowner)) then
  1478. begin
  1479. recstlist.add(recst);
  1480. symtablestack.pop(recst);
  1481. end;
  1482. read_anon_type(hdef,false);
  1483. block_type:=bt_var;
  1484. { allow only static fields reference to struct where they are declared }
  1485. if not (vd_class in options) and
  1486. (is_object(hdef) or is_record(hdef)) and
  1487. is_owned_by(tabstractrecorddef(recst.defowner),tabstractrecorddef(hdef)) then
  1488. begin
  1489. Message1(type_e_type_is_not_completly_defined, tabstractrecorddef(hdef).RttiName);
  1490. { for error recovery or compiler will crash later }
  1491. hdef:=generrordef;
  1492. end;
  1493. { restore stack }
  1494. for i:=recstlist.count-1 downto 0 do
  1495. begin
  1496. recst:=tabstractrecordsymtable(recstlist[i]);
  1497. symtablestack.push(recst);
  1498. end;
  1499. { Process procvar directives }
  1500. if maybe_parse_proc_directives(hdef) then
  1501. semicoloneaten:=true;
  1502. {$if defined(powerpc) or defined(powerpc64)}
  1503. { from gcc/gcc/config/rs6000/rs6000.h:
  1504. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1505. /* Return the alignment of a struct based on the Macintosh PowerPC
  1506. alignment rules. In general the alignment of a struct is
  1507. determined by the greatest alignment of its elements. However, the
  1508. PowerPC rules cause the alignment of a struct to peg at word
  1509. alignment except when the first field has greater than word
  1510. (32-bit) alignment, in which case the alignment is determined by
  1511. the alignment of the first field. */
  1512. }
  1513. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1514. is_first_type and
  1515. (symtablestack.top.symtabletype=recordsymtable) and
  1516. (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
  1517. begin
  1518. tempdef:=hdef;
  1519. while tempdef.typ=arraydef do
  1520. tempdef:=tarraydef(tempdef).elementdef;
  1521. if tempdef.typ<>recorddef then
  1522. maxpadalign:=tempdef.alignment
  1523. else
  1524. maxpadalign:=trecorddef(tempdef).padalignment;
  1525. if (maxpadalign>4) and
  1526. (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
  1527. trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
  1528. is_first_type:=false;
  1529. end;
  1530. {$endif powerpc or powerpc64}
  1531. { types that use init/final are not allowed in variant parts, but
  1532. classes are allowed }
  1533. if (variantrecordlevel>0) then
  1534. if is_managed_type(hdef) then
  1535. Message(parser_e_cant_use_inittable_here)
  1536. else
  1537. if hdef.typ=undefineddef then
  1538. Message(parser_e_cant_use_type_parameters_here);
  1539. { try to parse the hint directives }
  1540. hintsymoptions:=[];
  1541. deprecatedmsg:=nil;
  1542. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1543. { update variable type and hints }
  1544. for i:=0 to sc.count-1 do
  1545. begin
  1546. fieldvs:=tfieldvarsym(sc[i]);
  1547. fieldvs.vardef:=hdef;
  1548. { insert any additional hint directives }
  1549. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1550. if deprecatedmsg<>nil then
  1551. fieldvs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1552. end;
  1553. stringdispose(deprecatedmsg);
  1554. { Records and objects can't have default values }
  1555. { for a record there doesn't need to be a ; before the END or ) }
  1556. if not(token in [_END,_RKLAMMER]) and
  1557. not(semicoloneaten) then
  1558. consume(_SEMICOLON);
  1559. { Parse procvar directives after ; }
  1560. maybe_parse_proc_directives(hdef);
  1561. { Add calling convention for procvar }
  1562. if (hdef.typ=procvardef) and
  1563. (hdef.typesym=nil) then
  1564. handle_calling_convention(tprocvardef(hdef));
  1565. { check if it is a class field }
  1566. if (vd_object in options) then
  1567. begin
  1568. { if it is not a class var section and token=STATIC then it is a class field too }
  1569. if not (vd_class in options) and try_to_consume(_STATIC) then
  1570. begin
  1571. consume(_SEMICOLON);
  1572. include(options,vd_class);
  1573. removeclassoption:=true;
  1574. end;
  1575. end;
  1576. if vd_class in options then
  1577. begin
  1578. { add static flag and staticvarsyms }
  1579. for i:=0 to sc.count-1 do
  1580. begin
  1581. fieldvs:=tfieldvarsym(sc[i]);
  1582. include(fieldvs.symoptions,sp_static);
  1583. { generate the symbol which reserves the space }
  1584. static_name:=lower(generate_nested_name(recst,'_'))+'_'+fieldvs.name;
  1585. hstaticvs:=tstaticvarsym.create('$_static_'+static_name,vs_value,hdef,[]);
  1586. include(hstaticvs.symoptions,sp_internal);
  1587. recst.get_unit_symtable.insert(hstaticvs);
  1588. insertbssdata(hstaticvs);
  1589. { generate the symbol for the access }
  1590. sl:=tpropaccesslist.create;
  1591. sl.addsym(sl_load,hstaticvs);
  1592. recst.insert(tabsolutevarsym.create_ref('$'+static_name,hdef,sl));
  1593. end;
  1594. if removeclassoption then
  1595. begin
  1596. exclude(options,vd_class);
  1597. removeclassoption:=false;
  1598. end;
  1599. end;
  1600. if (visibility=vis_published) and
  1601. not(is_class(hdef)) then
  1602. begin
  1603. Message(parser_e_cant_publish_that);
  1604. visibility:=vis_public;
  1605. end;
  1606. if (visibility=vis_published) and
  1607. not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
  1608. not(m_delphi in current_settings.modeswitches) then
  1609. begin
  1610. Message(parser_e_only_publishable_classes_can_be_published);
  1611. visibility:=vis_public;
  1612. end;
  1613. { Generate field in the recordsymtable }
  1614. for i:=0 to sc.count-1 do
  1615. begin
  1616. fieldvs:=tfieldvarsym(sc[i]);
  1617. { static data fields are already inserted in the globalsymtable }
  1618. if not(sp_static in fieldvs.symoptions) then
  1619. recst.addfield(fieldvs,visibility);
  1620. end;
  1621. end;
  1622. recstlist.free;
  1623. if m_delphi in current_settings.modeswitches then
  1624. block_type:=bt_var_type
  1625. else
  1626. block_type:=old_block_type;
  1627. { Check for Case }
  1628. if (vd_record in options) and
  1629. try_to_consume(_CASE) then
  1630. begin
  1631. maxsize:=0;
  1632. maxalignment:=0;
  1633. maxpadalign:=0;
  1634. { including a field declaration? }
  1635. fieldvs:=nil;
  1636. sorg:=orgpattern;
  1637. hs:=pattern;
  1638. searchsym(hs,srsym,srsymtable);
  1639. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1640. begin
  1641. consume(_ID);
  1642. consume(_COLON);
  1643. fieldvs:=tfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1644. symtablestack.top.insert(fieldvs);
  1645. end;
  1646. read_anon_type(casetype,true);
  1647. block_type:=bt_var;
  1648. if assigned(fieldvs) then
  1649. begin
  1650. fieldvs.vardef:=casetype;
  1651. recst.addfield(fieldvs,recst.currentvisibility);
  1652. end;
  1653. if not(is_ordinal(casetype))
  1654. {$ifndef cpu64bitaddr}
  1655. or is_64bitint(casetype)
  1656. {$endif cpu64bitaddr}
  1657. then
  1658. Message(type_e_ordinal_expr_expected);
  1659. consume(_OF);
  1660. UnionSymtable:=trecordsymtable.create('',current_settings.packrecords);
  1661. UnionDef:=trecorddef.create('',unionsymtable);
  1662. uniondef.isunion:=true;
  1663. startvarrecsize:=UnionSymtable.datasize;
  1664. { align the bitpacking to the next byte }
  1665. UnionSymtable.datasize:=startvarrecsize;
  1666. startvarrecalign:=UnionSymtable.fieldalignment;
  1667. startpadalign:=Unionsymtable.padalignment;
  1668. symtablestack.push(UnionSymtable);
  1669. repeat
  1670. repeat
  1671. pt:=comp_expr(true,false);
  1672. if not(pt.nodetype=ordconstn) then
  1673. Message(parser_e_illegal_expression);
  1674. if try_to_consume(_POINTPOINT) then
  1675. pt:=crangenode.create(pt,comp_expr(true,false));
  1676. pt.free;
  1677. if token=_COMMA then
  1678. consume(_COMMA)
  1679. else
  1680. break;
  1681. until false;
  1682. if m_delphi in current_settings.modeswitches then
  1683. block_type:=bt_var_type
  1684. else
  1685. block_type:=old_block_type;
  1686. consume(_COLON);
  1687. { read the vars }
  1688. consume(_LKLAMMER);
  1689. inc(variantrecordlevel);
  1690. if token<>_RKLAMMER then
  1691. read_record_fields([vd_record]);
  1692. dec(variantrecordlevel);
  1693. consume(_RKLAMMER);
  1694. { calculates maximal variant size }
  1695. maxsize:=max(maxsize,unionsymtable.datasize);
  1696. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1697. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1698. { the items of the next variant are overlayed }
  1699. unionsymtable.datasize:=startvarrecsize;
  1700. unionsymtable.fieldalignment:=startvarrecalign;
  1701. unionsymtable.padalignment:=startpadalign;
  1702. if (token<>_END) and (token<>_RKLAMMER) then
  1703. consume(_SEMICOLON)
  1704. else
  1705. break;
  1706. until (token=_END) or (token=_RKLAMMER);
  1707. symtablestack.pop(UnionSymtable);
  1708. { at last set the record size to that of the biggest variant }
  1709. unionsymtable.datasize:=maxsize;
  1710. unionsymtable.fieldalignment:=maxalignment;
  1711. unionsymtable.addalignmentpadding;
  1712. {$if defined(powerpc) or defined(powerpc64)}
  1713. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1714. if (target_info.system in [system_powerpc_darwin, system_powerpc_macos, system_powerpc64_darwin]) and
  1715. is_first_type and
  1716. (recst.usefieldalignment=C_alignment) and
  1717. (maxpadalign>recst.padalignment) then
  1718. recst.padalignment:=maxpadalign;
  1719. {$endif powerpc or powerpc64}
  1720. { Align the offset where the union symtable is added }
  1721. case recst.usefieldalignment of
  1722. { allow the unionsymtable to be aligned however it wants }
  1723. { (within the global min/max limits) }
  1724. 0, { default }
  1725. C_alignment:
  1726. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  1727. { 1 byte alignment if we are bitpacked }
  1728. bit_alignment:
  1729. usedalign:=1;
  1730. mac68k_alignment:
  1731. usedalign:=2;
  1732. { otherwise alignment at the packrecords alignment of the }
  1733. { current record }
  1734. else
  1735. usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1736. end;
  1737. offset:=align(recst.datasize,usedalign);
  1738. recst.datasize:=offset+unionsymtable.datasize;
  1739. if unionsymtable.recordalignment>recst.fieldalignment then
  1740. recst.fieldalignment:=unionsymtable.recordalignment;
  1741. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  1742. uniondef.owner.deletedef(uniondef);
  1743. end;
  1744. { free the list }
  1745. sc.free;
  1746. {$ifdef powerpc}
  1747. is_first_type := false;
  1748. {$endif powerpc}
  1749. block_type:=old_block_type;
  1750. end;
  1751. end.