pdecvar.pas 78 KB

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