pdecvar.pas 79 KB

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