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,aasmdata,
  48. ncon,nmat,nadd,ncal,nset,ncnv,ninl,nld,nflw,nmem,nutils,
  49. { codegen }
  50. ncgutil,ngenutil,
  51. { parser }
  52. scanner,
  53. pbase,pexpr,ptype,ptconst,pdecsub,
  54. { link }
  55. import
  56. ;
  57. function read_property_dec(is_classproperty:boolean;astruct:tabstractrecorddef):tpropertysym;
  58. { convert a node tree to symlist and return the last
  59. symbol }
  60. function parse_symlist(pl:tpropaccesslist;out def:tdef):boolean;
  61. var
  62. idx : longint;
  63. sym : tsym;
  64. srsymtable : TSymtable;
  65. st : TSymtable;
  66. p : tnode;
  67. begin
  68. result:=true;
  69. def:=nil;
  70. if token=_ID then
  71. begin
  72. if assigned(astruct) then
  73. sym:=search_struct_member(astruct,pattern)
  74. else
  75. searchsym(pattern,sym,srsymtable);
  76. if assigned(sym) then
  77. begin
  78. if assigned(astruct) and
  79. not is_visible_for_object(sym,astruct) then
  80. Message(parser_e_cant_access_private_member);
  81. case sym.typ of
  82. fieldvarsym :
  83. begin
  84. addsymref(sym);
  85. pl.addsym(sl_load,sym);
  86. def:=tfieldvarsym(sym).vardef;
  87. end;
  88. procsym :
  89. begin
  90. addsymref(sym);
  91. pl.addsym(sl_call,sym);
  92. end;
  93. else
  94. begin
  95. Message1(parser_e_illegal_field_or_method,orgpattern);
  96. def:=generrordef;
  97. result:=false;
  98. end;
  99. end;
  100. end
  101. else
  102. begin
  103. Message1(parser_e_illegal_field_or_method,orgpattern);
  104. def:=generrordef;
  105. result:=false;
  106. end;
  107. consume(_ID);
  108. repeat
  109. case token of
  110. _ID,
  111. _SEMICOLON :
  112. begin
  113. break;
  114. end;
  115. _POINT :
  116. begin
  117. consume(_POINT);
  118. if assigned(def) then
  119. begin
  120. st:=def.GetSymtable(gs_record);
  121. if assigned(st) then
  122. begin
  123. sym:=tsym(st.Find(pattern));
  124. if not(assigned(sym)) and is_object(def) then
  125. sym:=search_struct_member(tobjectdef(def),pattern);
  126. if assigned(sym) then
  127. begin
  128. pl.addsym(sl_subscript,sym);
  129. case sym.typ of
  130. fieldvarsym :
  131. def:=tfieldvarsym(sym).vardef;
  132. else
  133. begin
  134. Message1(sym_e_illegal_field,orgpattern);
  135. result:=false;
  136. end;
  137. end;
  138. end
  139. else
  140. begin
  141. Message1(sym_e_illegal_field,orgpattern);
  142. result:=false;
  143. end;
  144. end
  145. else
  146. begin
  147. Message(parser_e_invalid_qualifier);
  148. result:=false;
  149. end;
  150. end
  151. else
  152. begin
  153. Message(parser_e_invalid_qualifier);
  154. result:=false;
  155. end;
  156. consume(_ID);
  157. end;
  158. _LECKKLAMMER :
  159. begin
  160. consume(_LECKKLAMMER);
  161. repeat
  162. if def.typ=arraydef then
  163. begin
  164. idx:=0;
  165. p:=comp_expr([ef_accept_equal]);
  166. if (not codegenerror) then
  167. begin
  168. if (p.nodetype=ordconstn) then
  169. begin
  170. { type/range checking }
  171. inserttypeconv(p,tarraydef(def).rangedef);
  172. if (Tordconstnode(p).value<int64(low(longint))) or
  173. (Tordconstnode(p).value>int64(high(longint))) then
  174. message(parser_e_array_range_out_of_bounds)
  175. else
  176. idx:=Tordconstnode(p).value.svalue
  177. end
  178. else
  179. Message(type_e_ordinal_expr_expected)
  180. end;
  181. pl.addconst(sl_vec,idx,p.resultdef);
  182. p.free;
  183. def:=tarraydef(def).elementdef;
  184. end
  185. else
  186. begin
  187. Message(parser_e_invalid_qualifier);
  188. result:=false;
  189. end;
  190. until not try_to_consume(_COMMA);
  191. consume(_RECKKLAMMER);
  192. end;
  193. else
  194. begin
  195. Message(parser_e_ill_property_access_sym);
  196. result:=false;
  197. break;
  198. end;
  199. end;
  200. until false;
  201. end
  202. else
  203. begin
  204. Message(parser_e_ill_property_access_sym);
  205. result:=false;
  206. end;
  207. end;
  208. function allow_default_property(p : tpropertysym) : boolean;
  209. begin
  210. allow_default_property:=
  211. (is_ordinal(p.propdef) or
  212. {$ifndef cpu64bitaddr}
  213. is_64bitint(p.propdef) or
  214. {$endif cpu64bitaddr}
  215. is_class(p.propdef) or
  216. is_single(p.propdef) or
  217. (p.propdef.typ in [classrefdef,pointerdef]) or
  218. is_smallset(p.propdef)
  219. ) and not
  220. (
  221. (p.propdef.typ=arraydef) and
  222. (ppo_indexed in p.propoptions)
  223. ) and not
  224. (ppo_hasparameters in p.propoptions);
  225. end;
  226. procedure create_accessor_procsym(p: tpropertysym; pd: tprocdef; const prefix: string;
  227. accesstype: tpropaccesslisttypes);
  228. var
  229. sym: tprocsym;
  230. begin
  231. handle_calling_convention(pd);
  232. sym:=cprocsym.create(prefix+lower(p.realname));
  233. symtablestack.top.insert(sym);
  234. pd.procsym:=sym;
  235. include(pd.procoptions,po_dispid);
  236. include(pd.procoptions,po_global);
  237. pd.visibility:=vis_private;
  238. proc_add_definition(pd);
  239. p.propaccesslist[accesstype].addsym(sl_call,sym);
  240. p.propaccesslist[accesstype].procdef:=pd;
  241. end;
  242. procedure parse_dispinterface(p : tpropertysym; readpd,writepd: tprocdef;
  243. var paranr: word);
  244. var
  245. hasread, haswrite: boolean;
  246. pt: tnode;
  247. hdispid: longint;
  248. hparavs: tparavarsym;
  249. begin
  250. p.propaccesslist[palt_read].clear;
  251. p.propaccesslist[palt_write].clear;
  252. hasread:=true;
  253. haswrite:=true;
  254. hdispid:=0;
  255. if try_to_consume(_READONLY) then
  256. haswrite:=false
  257. else if try_to_consume(_WRITEONLY) then
  258. hasread:=false;
  259. if try_to_consume(_DISPID) then
  260. begin
  261. pt:=comp_expr([ef_accept_equal]);
  262. if is_constintnode(pt) then
  263. if (Tordconstnode(pt).value<int64(low(longint))) or (Tordconstnode(pt).value>int64(high(longint))) then
  264. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(longint)),tostr(high(longint)))
  265. else
  266. hdispid:=Tordconstnode(pt).value.svalue
  267. else
  268. Message(parser_e_dispid_must_be_ord_const);
  269. pt.free;
  270. end
  271. else
  272. hdispid:=tobjectdef(astruct).get_next_dispid;
  273. { COM property is simply a pair of methods, tagged with 'propertyget'
  274. and 'propertyset' flags (or a single method if access is restricted).
  275. Creating these implicit accessor methods also allows the rest of compiler
  276. to handle dispinterface properties the same way as regular ones. }
  277. if hasread then
  278. begin
  279. readpd.returndef:=p.propdef;
  280. readpd.dispid:=hdispid;
  281. readpd.proctypeoption:=potype_propgetter;
  282. create_accessor_procsym(p,readpd,'get$',palt_read);
  283. end;
  284. if haswrite then
  285. begin
  286. { add an extra parameter, a placeholder of the value to set }
  287. inc(paranr);
  288. hparavs:=cparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  289. writepd.parast.insert(hparavs);
  290. writepd.proctypeoption:=potype_propsetter;
  291. writepd.dispid:=hdispid;
  292. create_accessor_procsym(p,writepd,'put$',palt_write);
  293. end;
  294. end;
  295. var
  296. sym : tsym;
  297. srsymtable: tsymtable;
  298. p : tpropertysym;
  299. overridden : tsym;
  300. varspez : tvarspez;
  301. hdef : tdef;
  302. arraytype : tdef;
  303. def : tdef;
  304. pt : tnode;
  305. sc : TFPObjectList;
  306. paranr : word;
  307. i : longint;
  308. ImplIntf : TImplementedInterface;
  309. found,
  310. gotreadorwrite: boolean;
  311. hreadparavs,
  312. hparavs : tparavarsym;
  313. storedprocdef: tprocvardef;
  314. readprocdef,
  315. writeprocdef : tprocdef;
  316. begin
  317. result:=nil;
  318. { Generate temp procdefs to search for matching read/write
  319. procedures. the readprocdef will store all definitions }
  320. paranr:=0;
  321. readprocdef:=cprocdef.create(normal_function_level,true);
  322. writeprocdef:=cprocdef.create(normal_function_level,true);
  323. readprocdef.struct:=astruct;
  324. writeprocdef.struct:=astruct;
  325. if assigned(astruct) and is_classproperty then
  326. begin
  327. readprocdef.procoptions:=[po_staticmethod,po_classmethod];
  328. writeprocdef.procoptions:=[po_staticmethod,po_classmethod];
  329. end;
  330. if token<>_ID then
  331. begin
  332. consume(_ID);
  333. consume(_SEMICOLON);
  334. exit;
  335. end;
  336. { Generate propertysym and insert in symtablestack }
  337. p:=cpropertysym.create(orgpattern);
  338. p.visibility:=symtablestack.top.currentvisibility;
  339. p.default:=longint($80000000);
  340. if is_classproperty then
  341. include(p.symoptions, sp_static);
  342. symtablestack.top.insert(p);
  343. consume(_ID);
  344. { property parameters ? }
  345. if try_to_consume(_LECKKLAMMER) then
  346. begin
  347. if (p.visibility=vis_published) and
  348. not (m_delphi in current_settings.modeswitches) then
  349. Message(parser_e_cant_publish_that_property);
  350. { create a list of the parameters }
  351. p.parast:=tparasymtable.create(nil,0);
  352. symtablestack.push(p.parast);
  353. sc:=TFPObjectList.create(false);
  354. repeat
  355. if try_to_consume(_VAR) then
  356. varspez:=vs_var
  357. else if try_to_consume(_CONST) then
  358. varspez:=vs_const
  359. else if try_to_consume(_CONSTREF) then
  360. varspez:=vs_constref
  361. else if (m_out in current_settings.modeswitches) and try_to_consume(_OUT) then
  362. varspez:=vs_out
  363. else
  364. varspez:=vs_value;
  365. sc.clear;
  366. repeat
  367. inc(paranr);
  368. hreadparavs:=cparavarsym.create(orgpattern,10*paranr,varspez,generrordef,[]);
  369. p.parast.insert(hreadparavs);
  370. sc.add(hreadparavs);
  371. consume(_ID);
  372. until not try_to_consume(_COMMA);
  373. if try_to_consume(_COLON) then
  374. begin
  375. if try_to_consume(_ARRAY) then
  376. begin
  377. consume(_OF);
  378. { define range and type of range }
  379. hdef:=carraydef.create(0,-1,s32inttype);
  380. { define field type }
  381. single_type(arraytype,[]);
  382. tarraydef(hdef).elementdef:=arraytype;
  383. end
  384. else
  385. single_type(hdef,[]);
  386. end
  387. else
  388. hdef:=cformaltype;
  389. for i:=0 to sc.count-1 do
  390. tparavarsym(sc[i]).vardef:=hdef;
  391. until not try_to_consume(_SEMICOLON);
  392. sc.free;
  393. symtablestack.pop(p.parast);
  394. consume(_RECKKLAMMER);
  395. { the parser need to know if a property has parameters, the
  396. index parameter doesn't count (PFV) }
  397. if paranr>0 then
  398. begin
  399. p.add_accessor_parameters(readprocdef,writeprocdef);
  400. include(p.propoptions,ppo_hasparameters);
  401. end;
  402. end;
  403. { overridden property ? }
  404. { force property interface
  405. there is a property parameter
  406. a global property }
  407. if (token=_COLON) or (paranr>0) or (astruct=nil) then
  408. begin
  409. consume(_COLON);
  410. single_type(p.propdef,[stoAllowSpecialization]);
  411. if is_dispinterface(astruct) and not is_automatable(p.propdef) then
  412. Message1(type_e_not_automatable,p.propdef.typename);
  413. if (idtoken=_INDEX) then
  414. begin
  415. consume(_INDEX);
  416. pt:=comp_expr([ef_accept_equal]);
  417. { Only allow enum and integer indexes. Convert all integer
  418. values to objpas.integer (s32int on 32- and 64-bit targets,
  419. s16int on 16- and 8-bit) to be compatible with delphi,
  420. because the procedure matching requires equal parameters }
  421. if is_constnode(pt) and
  422. is_ordinal(pt.resultdef)
  423. and (not is_64bitint(pt.resultdef))
  424. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  425. and (not is_32bitint(pt.resultdef))
  426. {$endif}
  427. then
  428. begin
  429. if is_integer(pt.resultdef) then
  430. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  431. inserttypeconv_internal(pt,s16inttype);
  432. {$else}
  433. inserttypeconv_internal(pt,s32inttype);
  434. {$endif}
  435. p.index:=tordconstnode(pt).value.svalue;
  436. end
  437. else
  438. begin
  439. Message(parser_e_invalid_property_index_value);
  440. p.index:=0;
  441. end;
  442. p.indexdef:=pt.resultdef;
  443. include(p.propoptions,ppo_indexed);
  444. { concat a longint to the para templates }
  445. p.add_index_parameter(paranr,readprocdef,writeprocdef);
  446. pt.free;
  447. end;
  448. end
  449. else
  450. begin
  451. { do an property override }
  452. if (astruct.typ=objectdef) and assigned(tobjectdef(astruct).childof) then
  453. overridden:=search_struct_member(tobjectdef(astruct).childof,p.name)
  454. else
  455. overridden:=nil;
  456. if assigned(overridden) and
  457. (overridden.typ=propertysym) and
  458. not(is_dispinterface(astruct)) then
  459. begin
  460. tpropertysym(overridden).makeduplicate(p,readprocdef,writeprocdef,paranr);
  461. p.register_override(tpropertysym(overridden));
  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. gotreadorwrite:=false;
  478. { parse accessors }
  479. if try_to_consume(_READ) then
  480. begin
  481. gotreadorwrite:=true;
  482. p.propaccesslist[palt_read].clear;
  483. if parse_symlist(p.propaccesslist[palt_read],def) then
  484. begin
  485. sym:=p.propaccesslist[palt_read].firstsym^.sym;
  486. { getter is a function returning the type of the property }
  487. if sym.typ=procsym then
  488. begin
  489. readprocdef.returndef:=p.propdef;
  490. { Insert hidden parameters }
  491. handle_calling_convention(readprocdef);
  492. end;
  493. p.add_getter_or_setter_for_sym(palt_read,sym,def,readprocdef);
  494. end;
  495. end
  496. else
  497. p.inherit_accessor(palt_read);
  498. if try_to_consume(_WRITE) then
  499. begin
  500. gotreadorwrite:=true;
  501. p.propaccesslist[palt_write].clear;
  502. if parse_symlist(p.propaccesslist[palt_write],def) then
  503. begin
  504. sym:=p.propaccesslist[palt_write].firstsym^.sym;
  505. if sym.typ=procsym then
  506. begin
  507. { settter is a procedure with an extra value parameter
  508. of the of the property }
  509. writeprocdef.returndef:=voidtype;
  510. inc(paranr);
  511. hparavs:=cparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  512. writeprocdef.parast.insert(hparavs);
  513. { Insert hidden parameters }
  514. handle_calling_convention(writeprocdef);
  515. end;
  516. p.add_getter_or_setter_for_sym(palt_write,sym,def,writeprocdef);
  517. end;
  518. end
  519. else
  520. p.inherit_accessor(palt_write);
  521. { a new property (needs to declare a getter or setter, except in
  522. an interface }
  523. if not(ppo_overrides in p.propoptions) and
  524. not is_interface(astruct) and
  525. not gotreadorwrite then
  526. Consume(_READ);
  527. end
  528. else
  529. parse_dispinterface(p,readprocdef,writeprocdef,paranr);
  530. { stored is not allowed for dispinterfaces, records or class properties }
  531. if assigned(astruct) and not(is_dispinterface(astruct) or is_record(astruct)) and not is_classproperty then
  532. begin
  533. { ppo_stored is default on for not overridden properties }
  534. if not assigned(p.overriddenpropsym) then
  535. include(p.propoptions,ppo_stored);
  536. if try_to_consume(_STORED) then
  537. begin
  538. include(p.propoptions,ppo_stored);
  539. p.propaccesslist[palt_stored].clear;
  540. if token=_ID then
  541. begin
  542. { in the case that idtoken=_DEFAULT }
  543. { we have to do nothing except }
  544. { setting ppo_stored, it's the same }
  545. { as stored true }
  546. if idtoken<>_DEFAULT then
  547. begin
  548. { parse_symlist cannot deal with constsyms, and
  549. we also don't want to put constsyms in symlists
  550. since they have to be evaluated immediately rather
  551. than each time the property is accessed
  552. The proper fix would be to always create a parse tree
  553. and then convert that one, if appropriate, to a symlist.
  554. Currently, we e.g. don't support any constant expressions
  555. yet either here, while Delphi does.
  556. }
  557. { make sure we don't let constants mask class fields/
  558. methods
  559. }
  560. sym:=nil;
  561. if (not assigned(astruct) or
  562. (search_struct_member(astruct,pattern)=nil)) and
  563. searchsym(pattern,sym,srsymtable) and
  564. (sym.typ = constsym) then
  565. begin
  566. addsymref(sym);
  567. if not is_boolean(tconstsym(sym).constdef) then
  568. Message(parser_e_stored_property_must_be_boolean)
  569. else if (tconstsym(sym).value.valueord=0) then
  570. { same as for _FALSE }
  571. exclude(p.propoptions,ppo_stored)
  572. else
  573. { same as for _TRUE }
  574. p.default:=longint($80000000);
  575. consume(_ID);
  576. end
  577. else if parse_symlist(p.propaccesslist[palt_stored],def) then
  578. begin
  579. sym:=p.propaccesslist[palt_stored].firstsym^.sym;
  580. case sym.typ of
  581. procsym :
  582. begin
  583. { Create a temporary procvardef to handle parameters }
  584. storedprocdef:=cprocvardef.create(normal_function_level);
  585. include(storedprocdef.procoptions,po_methodpointer);
  586. { Return type must be boolean }
  587. storedprocdef.returndef:=pasbool8type;
  588. { Add index parameter if needed }
  589. if ppo_indexed in p.propoptions then
  590. begin
  591. hparavs:=cparavarsym.create('$index',10,vs_value,p.indexdef,[]);
  592. storedprocdef.parast.insert(hparavs);
  593. end;
  594. { Insert hidden parameters }
  595. handle_calling_convention(storedprocdef);
  596. p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
  597. if not assigned(p.propaccesslist[palt_stored].procdef) then
  598. message(parser_e_ill_property_storage_sym);
  599. { Not needed anymore }
  600. storedprocdef.owner.deletedef(storedprocdef);
  601. end;
  602. fieldvarsym :
  603. begin
  604. if not assigned(def) then
  605. internalerror(200310073);
  606. if (ppo_hasparameters in p.propoptions) or
  607. not(is_boolean(def)) then
  608. Message(parser_e_stored_property_must_be_boolean);
  609. end;
  610. else
  611. Message(parser_e_ill_property_access_sym);
  612. end;
  613. end;
  614. end;
  615. end;
  616. end;
  617. end;
  618. if not is_record(astruct) and try_to_consume(_DEFAULT) then
  619. begin
  620. if not allow_default_property(p) then
  621. begin
  622. Message(parser_e_property_cant_have_a_default_value);
  623. { Error recovery }
  624. pt:=comp_expr([ef_accept_equal]);
  625. pt.free;
  626. end
  627. else
  628. begin
  629. { Get the result of the default, the firstpass is
  630. needed to support values like -1 }
  631. pt:=comp_expr([ef_accept_equal]);
  632. if (p.propdef.typ=setdef) and
  633. (pt.nodetype=arrayconstructorn) then
  634. begin
  635. arrayconstructor_to_set(pt);
  636. do_typecheckpass(pt);
  637. end;
  638. inserttypeconv(pt,p.propdef);
  639. if not(is_constnode(pt)) then
  640. Message(parser_e_property_default_value_must_const);
  641. { Set default value }
  642. case pt.nodetype of
  643. setconstn :
  644. p.default:=plongint(tsetconstnode(pt).value_set)^;
  645. ordconstn :
  646. if (Tordconstnode(pt).value<int64(low(longint))) or
  647. (Tordconstnode(pt).value>int64(high(cardinal))) then
  648. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(longint)),tostr(high(cardinal)))
  649. else
  650. p.default:=longint(tordconstnode(pt).value.svalue);
  651. niln :
  652. p.default:=0;
  653. realconstn:
  654. p.default:=longint(single(trealconstnode(pt).value_real));
  655. end;
  656. pt.free;
  657. end;
  658. end
  659. else if not is_record(astruct) and try_to_consume(_NODEFAULT) then
  660. begin
  661. p.default:=longint($80000000);
  662. end;
  663. (*
  664. else {if allow_default_property(p) then
  665. begin
  666. p.default:=longint($80000000);
  667. end;
  668. *)
  669. { Parse possible "implements" keyword }
  670. if not is_record(astruct) and try_to_consume(_IMPLEMENTS) then
  671. repeat
  672. single_type(def,[]);
  673. if not(is_interface(def)) then
  674. message(parser_e_class_implements_must_be_interface);
  675. if is_interface(p.propdef) then
  676. begin
  677. { an interface type may delegate itself or one of its ancestors }
  678. if not def_is_related(p.propdef,def) then
  679. begin
  680. message2(parser_e_implements_must_have_correct_type,def.typename,p.propdef.typename);
  681. exit;
  682. end;
  683. end
  684. else if is_class(p.propdef) then
  685. begin
  686. ImplIntf:=find_implemented_interface(tobjectdef(p.propdef),tobjectdef(def));
  687. if assigned(ImplIntf) then
  688. begin
  689. if compare_defs(ImplIntf.IntfDef,def,nothingn)<te_equal then
  690. begin
  691. message2(parser_e_implements_must_have_correct_type,ImplIntf.IntfDef.typename,def.typename);
  692. exit;
  693. end;
  694. end
  695. else
  696. begin
  697. message2(parser_e_class_doesnt_implement_interface,p.propdef.typename,def.typename);
  698. exit;
  699. end;
  700. end
  701. else
  702. begin
  703. message(parser_e_implements_must_be_class_or_interface);
  704. exit;
  705. end;
  706. if not assigned(p.propaccesslist[palt_read].firstsym) then
  707. begin
  708. message(parser_e_implements_must_read_specifier);
  709. exit;
  710. end;
  711. if assigned(p.propaccesslist[palt_read].procdef) and
  712. (tprocdef(p.propaccesslist[palt_read].procdef).proccalloption<>pocall_default) then
  713. message(parser_e_implements_getter_not_default_cc);
  714. if assigned(p.propaccesslist[palt_write].firstsym) then
  715. begin
  716. message(parser_e_implements_must_not_have_write_specifier);
  717. exit;
  718. end;
  719. if assigned(p.propaccesslist[palt_stored].firstsym) then
  720. begin
  721. message(parser_e_implements_must_not_have_stored_specifier);
  722. exit;
  723. end;
  724. found:=false;
  725. ImplIntf:=nil;
  726. for i:=0 to tobjectdef(astruct).ImplementedInterfaces.Count-1 do
  727. begin
  728. ImplIntf:=TImplementedInterface(tobjectdef(astruct).ImplementedInterfaces[i]);
  729. if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
  730. begin
  731. found:=true;
  732. break;
  733. end;
  734. end;
  735. if found then
  736. begin
  737. { An interface may not be delegated by more than one property,
  738. it also may not have method mappings. }
  739. if Assigned(ImplIntf.ImplementsGetter) then
  740. message1(parser_e_duplicate_implements_clause,ImplIntf.IntfDef.typename);
  741. if Assigned(ImplIntf.NameMappings) then
  742. message2(parser_e_mapping_no_implements,ImplIntf.IntfDef.typename,astruct.objrealname^);
  743. ImplIntf.ImplementsGetter:=p;
  744. ImplIntf.VtblImplIntf:=ImplIntf;
  745. case p.propaccesslist[palt_read].firstsym^.sym.typ of
  746. procsym :
  747. begin
  748. if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) and
  749. not is_objectpascal_helper(tprocdef(p.propaccesslist[palt_read].procdef).struct) then
  750. ImplIntf.IType:=etVirtualMethodResult
  751. else
  752. ImplIntf.IType:=etStaticMethodResult;
  753. end;
  754. fieldvarsym :
  755. begin
  756. ImplIntf.IType:=etFieldValue;
  757. { this must be done in a more robust way. Can't read the
  758. fieldvarsym's fieldoffset yet, because it may not yet
  759. be set }
  760. ImplIntf.ImplementsField:=p.propaccesslist[palt_read].firstsym^.sym;
  761. end
  762. else
  763. internalerror(200802161);
  764. end;
  765. if not is_interface(p.propdef) then
  766. case ImplIntf.IType of
  767. etVirtualMethodResult: ImplIntf.IType := etVirtualMethodClass;
  768. etStaticMethodResult: ImplIntf.IType := etStaticMethodClass;
  769. etFieldValue: ImplIntf.IType := etFieldValueClass;
  770. else
  771. internalerror(200912101);
  772. end;
  773. end
  774. else
  775. message1(parser_e_implements_uses_non_implemented_interface,def.typename);
  776. until not try_to_consume(_COMMA);
  777. { remove unneeded procdefs }
  778. if readprocdef.proctypeoption<>potype_propgetter then
  779. readprocdef.owner.deletedef(readprocdef);
  780. if writeprocdef.proctypeoption<>potype_propsetter then
  781. writeprocdef.owner.deletedef(writeprocdef);
  782. result:=p;
  783. end;
  784. function maybe_parse_proc_directives(def:tdef):boolean;
  785. var
  786. newtype : ttypesym;
  787. begin
  788. result:=false;
  789. { Process procvar directives before = and ; }
  790. if (def.typ=procvardef) and
  791. (def.typesym=nil) and
  792. check_proc_directive(true) then
  793. begin
  794. newtype:=ctypesym.create('unnamed',def,true);
  795. parse_var_proc_directives(tsym(newtype));
  796. newtype.typedef:=nil;
  797. def.typesym:=nil;
  798. newtype.free;
  799. result:=true;
  800. end;
  801. end;
  802. const
  803. variantrecordlevel : longint = 0;
  804. procedure read_public_and_external_sc(sc:TFPObjectList);
  805. var
  806. vs: tabstractvarsym;
  807. begin
  808. { only allowed for one var }
  809. vs:=tabstractvarsym(sc[0]);
  810. if sc.count>1 then
  811. Message1(parser_e_directive_only_one_var,arraytokeninfo[idtoken].str);
  812. read_public_and_external(vs);
  813. end;
  814. procedure read_public_and_external(vs: tabstractvarsym);
  815. var
  816. is_dll,
  817. is_cdecl,
  818. is_external_var,
  819. is_weak_external,
  820. is_public_var : boolean;
  821. dll_name,section_name,
  822. C_name,mangledname : string;
  823. begin
  824. { only allowed for one var }
  825. { only allow external and public on global symbols }
  826. if vs.typ<>staticvarsym then
  827. begin
  828. Message(parser_e_no_local_var_external);
  829. exit;
  830. end;
  831. { defaults }
  832. is_dll:=false;
  833. is_cdecl:=false;
  834. is_external_var:=false;
  835. is_public_var:=false;
  836. section_name := '';
  837. dll_name := '';
  838. C_name:=vs.realname;
  839. { macpas specific handling due to some switches}
  840. if (m_mac in current_settings.modeswitches) then
  841. begin
  842. if (cs_external_var in current_settings.localswitches) then
  843. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  844. is_cdecl:=true;
  845. is_external_var:=true;
  846. end
  847. else if (cs_externally_visible in current_settings.localswitches) then
  848. begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
  849. is_cdecl:=true;
  850. is_public_var:=true;
  851. end;
  852. end;
  853. { cdecl }
  854. if try_to_consume(_CVAR) then
  855. begin
  856. consume(_SEMICOLON);
  857. is_cdecl:=true;
  858. end;
  859. { external }
  860. is_weak_external:=try_to_consume(_WEAKEXTERNAL);
  861. if is_weak_external or
  862. try_to_consume(_EXTERNAL) then
  863. begin
  864. is_external_var:=true;
  865. if (idtoken<>_NAME) and (token<>_SEMICOLON) then
  866. begin
  867. is_dll:=true;
  868. dll_name:=get_stringconst;
  869. if ExtractFileExt(dll_name)='' then
  870. dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
  871. end;
  872. if not(is_cdecl) and try_to_consume(_NAME) then
  873. C_name:=get_stringconst;
  874. consume(_SEMICOLON);
  875. end;
  876. { export or public }
  877. if idtoken in [_EXPORT,_PUBLIC] then
  878. begin
  879. consume(_ID);
  880. if is_external_var then
  881. Message(parser_e_not_external_and_export)
  882. else
  883. is_public_var:=true;
  884. if try_to_consume(_NAME) then
  885. C_name:=get_stringconst;
  886. if (target_info.system in systems_allow_section_no_semicolon) and
  887. (vs.typ=staticvarsym) and
  888. try_to_consume (_SECTION) then
  889. section_name:=get_stringconst;
  890. consume(_SEMICOLON);
  891. end;
  892. { Windows uses an indirect reference using import tables }
  893. if is_dll and
  894. (target_info.system in systems_all_windows) then
  895. include(vs.varoptions,vo_is_dll_var);
  896. { This can only happen if vs.typ=staticvarsym }
  897. if section_name<>'' then
  898. begin
  899. tstaticvarsym(vs).section:=section_name;
  900. include(vs.varoptions,vo_has_section);
  901. end;
  902. { Add C _ prefix }
  903. if is_cdecl or
  904. (
  905. is_dll and
  906. (target_info.system in systems_darwin)
  907. ) then
  908. C_Name := target_info.Cprefix+C_Name;
  909. if is_public_var then
  910. begin
  911. include(vs.varoptions,vo_is_public);
  912. vs.varregable := vr_none;
  913. { mark as referenced }
  914. inc(vs.refs);
  915. end;
  916. mangledname:=C_name;
  917. { now we can insert it in the import lib if its a dll, or
  918. add it to the externals }
  919. if is_external_var then
  920. begin
  921. if vo_is_typed_const in vs.varoptions then
  922. Message(parser_e_initialized_not_for_external);
  923. include(vs.varoptions,vo_is_external);
  924. if (is_weak_external) then
  925. begin
  926. if not(target_info.system in systems_weak_linking) then
  927. message(parser_e_weak_external_not_supported);
  928. include(vs.varoptions,vo_is_weak_external);
  929. end;
  930. vs.varregable := vr_none;
  931. if is_dll then
  932. begin
  933. if target_info.system in (systems_all_windows + systems_nativent +
  934. [system_i386_emx, system_i386_os2]) then
  935. mangledname:=make_dllmangledname(dll_name,C_name,0,pocall_none);
  936. current_module.AddExternalImport(dll_name,C_Name,mangledname,0,true,false);
  937. end
  938. else
  939. if tf_has_dllscanner in target_info.flags then
  940. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  941. end;
  942. { Set the assembler name }
  943. tstaticvarsym(vs).set_mangledbasename(mangledname);
  944. tstaticvarsym(vs).set_mangledname(mangledname);
  945. end;
  946. procedure try_consume_sectiondirective(var asection: ansistring);
  947. begin
  948. if idtoken=_SECTION then
  949. begin
  950. consume(_ID);
  951. asection:=get_stringconst;
  952. consume(_SEMICOLON);
  953. end;
  954. end;
  955. procedure try_read_field_external(vs: tabstractvarsym);
  956. var
  957. extname: string;
  958. begin
  959. if try_to_consume(_EXTERNAL) then
  960. begin
  961. consume(_NAME);
  962. extname:=get_stringconst;
  963. tfieldvarsym(vs).set_externalname(extname);
  964. consume(_SEMICOLON);
  965. end;
  966. end;
  967. procedure try_read_field_external_sc(sc:TFPObjectList);
  968. var
  969. vs: tabstractvarsym;
  970. begin
  971. { only allowed for one var }
  972. vs:=tabstractvarsym(sc[0]);
  973. if sc.count>1 then
  974. Message1(parser_e_directive_only_one_var,arraytokeninfo[idtoken].str);
  975. try_read_field_external(vs);
  976. end;
  977. procedure read_var_decls(options:Tvar_dec_options;out had_generic:boolean);
  978. procedure read_default_value(sc : TFPObjectList);
  979. var
  980. vs : tabstractnormalvarsym;
  981. tcsym : tstaticvarsym;
  982. templist : tasmlist;
  983. begin
  984. vs:=tabstractnormalvarsym(sc[0]);
  985. if sc.count>1 then
  986. Message(parser_e_initialized_only_one_var);
  987. if vo_is_thread_var in vs.varoptions then
  988. Message(parser_e_initialized_not_for_threadvar);
  989. consume(_EQ);
  990. case vs.typ of
  991. localvarsym :
  992. begin
  993. tcsym:=cstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[],true);
  994. include(tcsym.symoptions,sp_internal);
  995. symtablestack.top.insert(tcsym);
  996. templist:=tasmlist.create;
  997. read_typed_const(templist,tcsym,false);
  998. { in case of a generic routine, this initialisation value is not
  999. used, and will be re-parsed during specialisations (and the
  1000. current version is not type-correct and hence breaks code
  1001. generation for LLVM) }
  1002. if not parse_generic then
  1003. begin
  1004. vs.defaultconstsym:=tcsym;
  1005. current_asmdata.asmlists[al_typedconsts].concatlist(templist);
  1006. end;
  1007. templist.free;
  1008. end;
  1009. staticvarsym :
  1010. begin
  1011. read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs),false);
  1012. end;
  1013. else
  1014. internalerror(200611051);
  1015. end;
  1016. vs.varstate:=vs_initialised;
  1017. end;
  1018. {$ifdef gpc_mode}
  1019. procedure read_gpc_name(sc : TFPObjectList);
  1020. var
  1021. vs : tabstractnormalvarsym;
  1022. C_Name : string;
  1023. begin
  1024. consume(_ID);
  1025. C_Name:=get_stringconst;
  1026. vs:=tabstractnormalvarsym(sc[0]);
  1027. if sc.count>1 then
  1028. Message(parser_e_directive_only_one_var,'ABSOLUTE');
  1029. if vs.typ=staticvarsym then
  1030. begin
  1031. tstaticvarsym(vs).set_mangledname(C_Name);
  1032. include(vs.varoptions,vo_is_external);
  1033. end
  1034. else
  1035. Message(parser_e_no_local_var_external);
  1036. end;
  1037. {$endif}
  1038. procedure read_absolute(sc : TFPObjectList);
  1039. var
  1040. vs : tabstractvarsym;
  1041. abssym : tabsolutevarsym;
  1042. pt,hp : tnode;
  1043. st : tsymtable;
  1044. {$if defined(i386) or defined(i8086)}
  1045. tmpaddr : int64;
  1046. {$endif defined(i386) or defined(i8086)}
  1047. begin
  1048. abssym:=nil;
  1049. { only allowed for one var }
  1050. vs:=tabstractvarsym(sc[0]);
  1051. if sc.count>1 then
  1052. Message1(parser_e_directive_only_one_var,'ABSOLUTE');
  1053. if vo_is_typed_const in vs.varoptions then
  1054. Message(parser_e_initialized_not_for_external);
  1055. { parse the rest }
  1056. pt:=expr(true);
  1057. { check allowed absolute types }
  1058. if (pt.nodetype=stringconstn) or
  1059. (is_constcharnode(pt)) then
  1060. begin
  1061. abssym:=cabsolutevarsym.create(vs.realname,vs.vardef);
  1062. abssym.fileinfo:=vs.fileinfo;
  1063. if pt.nodetype=stringconstn then
  1064. abssym.asmname:=stringdup(strpas(tstringconstnode(pt).value_str))
  1065. else
  1066. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  1067. consume(token);
  1068. abssym.abstyp:=toasm;
  1069. end
  1070. { address }
  1071. else if is_constintnode(pt) then
  1072. begin
  1073. abssym:=cabsolutevarsym.create(vs.realname,vs.vardef);
  1074. abssym.fileinfo:=vs.fileinfo;
  1075. abssym.abstyp:=toaddr;
  1076. {$ifndef cpu64bitaddr}
  1077. { on 64 bit systems, abssym.addroffset is a qword and hence this
  1078. test is useless (value is a 64 bit entity) and will always fail
  1079. for positive values (since int64(high(abssym.addroffset))=-1
  1080. }
  1081. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  1082. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  1083. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(abssym.addroffset)),tostr(high(abssym.addroffset)))
  1084. else
  1085. {$endif}
  1086. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  1087. {$if defined(i386) or defined(i8086)}
  1088. tcpuabsolutevarsym(abssym).absseg:=false;
  1089. if (target_info.system in [system_i386_go32v2,system_i386_watcom,system_i8086_msdos,system_i8086_win16,system_i8086_embedded]) and
  1090. try_to_consume(_COLON) then
  1091. begin
  1092. pt.free;
  1093. pt:=expr(true);
  1094. if is_constintnode(pt) then
  1095. begin
  1096. {$if defined(i8086)}
  1097. tcpuabsolutevarsym(abssym).addrsegment:=abssym.addroffset;
  1098. tmpaddr:=tordconstnode(pt).value.svalue;
  1099. if (tmpaddr<int64(low(abssym.addroffset))) or
  1100. (tmpaddr>int64(high(abssym.addroffset))) then
  1101. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(abssym.addroffset)),tostr(high(abssym.addroffset)))
  1102. else
  1103. abssym.addroffset:=tmpaddr;
  1104. {$elseif defined(i386)}
  1105. tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  1106. if (tmpaddr<int64(low(abssym.addroffset))) or
  1107. (tmpaddr>int64(high(abssym.addroffset))) then
  1108. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(abssym.addroffset)),tostr(high(abssym.addroffset)))
  1109. else
  1110. abssym.addroffset:=tmpaddr;
  1111. {$endif}
  1112. tcpuabsolutevarsym(abssym).absseg:=true;
  1113. end
  1114. else
  1115. Message(type_e_ordinal_expr_expected);
  1116. end;
  1117. {$endif i386 or i8086}
  1118. end
  1119. { variable }
  1120. else
  1121. begin
  1122. { we have to be able to take the address of the absolute
  1123. expression
  1124. }
  1125. valid_for_addr(pt,true);
  1126. { remove subscriptn before checking for loadn }
  1127. hp:=pt;
  1128. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1129. begin
  1130. { check for implicit dereferencing and reject it }
  1131. if (hp.nodetype in [subscriptn,vecn]) then
  1132. begin
  1133. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1134. break;
  1135. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1136. (pchar_var[5] is a pchar_2_string typeconv ->
  1137. the vecn only sees an array of char)
  1138. I don't know if all of these type conversions are
  1139. possible, but they're definitely all bad.
  1140. }
  1141. if (tunarynode(hp).left.nodetype=typeconvn) and
  1142. (ttypeconvnode(tunarynode(hp).left).convtype in
  1143. [tc_pchar_2_string,tc_pointer_2_array,
  1144. tc_intf_2_string,tc_intf_2_guid,
  1145. tc_dynarray_2_variant,tc_interface_2_variant,
  1146. tc_array_2_dynarray]) then
  1147. break;
  1148. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1149. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1150. break;
  1151. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1152. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1153. break;
  1154. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1155. break;
  1156. end;
  1157. hp:=tunarynode(hp).left;
  1158. end;
  1159. if (hp.nodetype=loadn) then
  1160. begin
  1161. { we should check the result type of loadn }
  1162. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym]) then
  1163. Message(parser_e_absolute_only_to_var_or_const);
  1164. abssym:=cabsolutevarsym.create(vs.realname,vs.vardef);
  1165. abssym.fileinfo:=vs.fileinfo;
  1166. abssym.abstyp:=tovar;
  1167. abssym.ref:=node_to_propaccesslist(pt);
  1168. { if the sizes are different, can't be a regvar since you }
  1169. { can't be "absolute upper 8 bits of a register" (except }
  1170. { if its a record field of the same size of a record }
  1171. { regvar, but in that case pt.resultdef.size will have }
  1172. { the same size since it refers to the field and not to }
  1173. { the whole record -- which is why we use pt and not hp) }
  1174. { we can't take the size of an open array }
  1175. if is_open_array(pt.resultdef) or
  1176. (vs.vardef.size <> pt.resultdef.size) then
  1177. make_not_regable(pt,[ra_addr_regable]);
  1178. end
  1179. else
  1180. Message(parser_e_absolute_only_to_var_or_const);
  1181. end;
  1182. pt.free;
  1183. { replace old varsym with the new absolutevarsym }
  1184. if assigned(abssym) then
  1185. begin
  1186. st:=vs.owner;
  1187. vs.owner.Delete(vs);
  1188. st.insert(abssym);
  1189. sc[0]:=abssym;
  1190. end;
  1191. end;
  1192. var
  1193. sc : TFPObjectList;
  1194. vs : tabstractvarsym;
  1195. hdef : tdef;
  1196. i : longint;
  1197. first,
  1198. isgeneric,
  1199. semicoloneaten,
  1200. allowdefaultvalue,
  1201. hasdefaultvalue : boolean;
  1202. hintsymoptions : tsymoptions;
  1203. deprecatedmsg : pshortstring;
  1204. old_block_type : tblock_type;
  1205. sectionname : ansistring;
  1206. tmp_filepos,
  1207. old_current_filepos : tfileposinfo;
  1208. begin
  1209. old_block_type:=block_type;
  1210. block_type:=bt_var;
  1211. { Force an expected ID error message }
  1212. if not (token in [_ID,_CASE,_END]) then
  1213. consume(_ID);
  1214. { read vars }
  1215. sc:=TFPObjectList.create(false);
  1216. first:=true;
  1217. had_generic:=false;
  1218. vs:=nil;
  1219. fillchar(tmp_filepos,sizeof(tmp_filepos),0);
  1220. while (token=_ID) do
  1221. begin
  1222. semicoloneaten:=false;
  1223. hasdefaultvalue:=false;
  1224. allowdefaultvalue:=true;
  1225. sc.clear;
  1226. repeat
  1227. if (token = _ID) then
  1228. begin
  1229. isgeneric:=(vd_check_generic in options) and
  1230. not (m_delphi in current_settings.modeswitches) and
  1231. (idtoken=_GENERIC);
  1232. case symtablestack.top.symtabletype of
  1233. localsymtable :
  1234. vs:=clocalvarsym.create(orgpattern,vs_value,generrordef,[],false);
  1235. staticsymtable,
  1236. globalsymtable :
  1237. begin
  1238. vs:=cstaticvarsym.create(orgpattern,vs_value,generrordef,[],false);
  1239. if vd_threadvar in options then
  1240. include(vs.varoptions,vo_is_thread_var);
  1241. end;
  1242. else
  1243. internalerror(200411064);
  1244. end;
  1245. sc.add(vs);
  1246. if isgeneric then
  1247. tmp_filepos:=current_filepos;
  1248. end
  1249. else
  1250. isgeneric:=false;
  1251. consume(_ID);
  1252. { when the first variable had been read the next declaration could be
  1253. a "generic procedure", "generic function" or
  1254. "generic class (function/procedure)" }
  1255. if not first
  1256. and isgeneric
  1257. and (sc.count=1)
  1258. and (token in [_PROCEDURE,_FUNCTION,_CLASS]) then
  1259. begin
  1260. vs.free;
  1261. sc.clear;
  1262. had_generic:=true;
  1263. break;
  1264. end
  1265. else
  1266. begin
  1267. vs.register_sym;
  1268. symtablestack.top.insert(vs);
  1269. if isgeneric then
  1270. begin
  1271. { ensure correct error position }
  1272. old_current_filepos:=current_filepos;
  1273. current_filepos:=tmp_filepos;
  1274. symtablestack.top.insert(vs);
  1275. current_filepos:=old_current_filepos;
  1276. end;
  1277. end;
  1278. until not try_to_consume(_COMMA);
  1279. if had_generic then
  1280. break;
  1281. { read variable type def }
  1282. block_type:=bt_var_type;
  1283. consume(_COLON);
  1284. {$ifdef gpc_mode}
  1285. if (m_gpc in current_settings.modeswitches) and
  1286. (token=_ID) and
  1287. (orgpattern='__asmname__') then
  1288. read_gpc_name(sc);
  1289. {$endif}
  1290. read_anon_type(hdef,false);
  1291. maybe_guarantee_record_typesym(hdef,symtablestack.top);
  1292. for i:=0 to sc.count-1 do
  1293. begin
  1294. vs:=tabstractvarsym(sc[i]);
  1295. vs.vardef:=hdef;
  1296. end;
  1297. block_type:=bt_var;
  1298. { Process procvar directives }
  1299. if maybe_parse_proc_directives(hdef) then
  1300. semicoloneaten:=true;
  1301. { check for absolute }
  1302. if try_to_consume(_ABSOLUTE) then
  1303. begin
  1304. read_absolute(sc);
  1305. allowdefaultvalue:=false;
  1306. end;
  1307. { Check for EXTERNAL etc directives before a semicolon }
  1308. if (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) then
  1309. begin
  1310. read_public_and_external_sc(sc);
  1311. allowdefaultvalue:=false;
  1312. semicoloneaten:=true;
  1313. end;
  1314. { try to parse the hint directives }
  1315. hintsymoptions:=[];
  1316. deprecatedmsg:=nil;
  1317. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1318. for i:=0 to sc.count-1 do
  1319. begin
  1320. vs:=tabstractvarsym(sc[i]);
  1321. vs.symoptions := vs.symoptions + hintsymoptions;
  1322. if deprecatedmsg<>nil then
  1323. vs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1324. end;
  1325. stringdispose(deprecatedmsg);
  1326. { Handling of Delphi typed const = initialized vars }
  1327. if allowdefaultvalue and
  1328. (token=_EQ) and
  1329. not(m_tp7 in current_settings.modeswitches) and
  1330. (symtablestack.top.symtabletype<>parasymtable) then
  1331. begin
  1332. { Add calling convention for procvar }
  1333. if (hdef.typ=procvardef) and
  1334. (hdef.typesym=nil) then
  1335. handle_calling_convention(tprocvardef(hdef));
  1336. read_default_value(sc);
  1337. hasdefaultvalue:=true;
  1338. end
  1339. else
  1340. begin
  1341. if not(semicoloneaten) then
  1342. consume(_SEMICOLON);
  1343. end;
  1344. { Support calling convention for procvars after semicolon }
  1345. if not(hasdefaultvalue) and
  1346. (hdef.typ=procvardef) and
  1347. (hdef.typesym=nil) then
  1348. begin
  1349. { Parse procvar directives after ; }
  1350. maybe_parse_proc_directives(hdef);
  1351. { Add calling convention for procvar }
  1352. handle_calling_convention(tprocvardef(hdef));
  1353. { Handling of Delphi typed const = initialized vars }
  1354. if (token=_EQ) and
  1355. not(m_tp7 in current_settings.modeswitches) and
  1356. (symtablestack.top.symtabletype<>parasymtable) then
  1357. begin
  1358. read_default_value(sc);
  1359. hasdefaultvalue:=true;
  1360. end;
  1361. end;
  1362. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1363. if (
  1364. (
  1365. (idtoken in [_EXPORT,_EXTERNAL,_WEAKEXTERNAL,_PUBLIC,_CVAR]) and
  1366. (m_cvar_support in current_settings.modeswitches)
  1367. ) or
  1368. (
  1369. (m_mac in current_settings.modeswitches) and
  1370. (
  1371. (cs_external_var in current_settings.localswitches) or
  1372. (cs_externally_visible in current_settings.localswitches)
  1373. )
  1374. )
  1375. ) then
  1376. read_public_and_external_sc(sc);
  1377. { try to parse a section directive }
  1378. if (target_info.system in systems_allow_section) and
  1379. (symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) and
  1380. (idtoken=_SECTION) then
  1381. begin
  1382. try_consume_sectiondirective(sectionname);
  1383. if sectionname<>'' then
  1384. begin
  1385. for i:=0 to sc.count-1 do
  1386. begin
  1387. vs:=tabstractvarsym(sc[i]);
  1388. if (vs.varoptions *[vo_is_external,vo_is_weak_external])<>[] then
  1389. Message(parser_e_externals_no_section);
  1390. if vs.typ<>staticvarsym then
  1391. Message(parser_e_section_no_locals);
  1392. tstaticvarsym(vs).section:=sectionname;
  1393. include(vs.varoptions, vo_has_section);
  1394. end;
  1395. end;
  1396. end;
  1397. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1398. for i:=0 to sc.count-1 do
  1399. begin
  1400. vs:=tabstractvarsym(sc[i]);
  1401. if (vs.typ=staticvarsym) and
  1402. not(vo_is_typed_const in vs.varoptions) and
  1403. not(vo_is_external in vs.varoptions) then
  1404. cnodeutils.insertbssdata(tstaticvarsym(vs));
  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.