pdecvar.pas 80 KB

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