pdecvar.pas 79 KB

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