pdecvar.pas 79 KB

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