2
0

pdecvar.pas 80 KB

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