pdecvar.pas 80 KB

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