pdecvar.pas 77 KB

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