pdecvar.pas 87 KB

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