pdecvar.pas 82 KB

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