pdecvar.pas 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143
  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)) then
  481. begin
  482. { ignore is_publishable for interfaces (related to $M+ directive).
  483. $M has effect on visibility of default section for classes.
  484. Interface has always only public section (fix for problem in tb0631.pp) }
  485. if (sp_static in p.symoptions) or ((p.propdef.is_publishable=pp_error) and not is_interface(astruct)) then
  486. begin
  487. Message(parser_e_cant_publish_that_property);
  488. p.visibility:=vis_public;
  489. end
  490. else
  491. if (p.propdef.is_publishable=pp_ignore) and not is_interface(astruct) then
  492. begin
  493. Message(parser_w_ignoring_published_property);
  494. p.visibility:=vis_public;
  495. end;
  496. end;
  497. if not(is_dispinterface(astruct)) then
  498. begin
  499. gotreadorwrite:=false;
  500. { parse accessors }
  501. if try_to_consume(_READ) then
  502. begin
  503. gotreadorwrite:=true;
  504. p.propaccesslist[palt_read].clear;
  505. if parse_symlist(p.propaccesslist[palt_read],def) then
  506. begin
  507. sym:=p.propaccesslist[palt_read].firstsym^.sym;
  508. { getter is a function returning the type of the property }
  509. if sym.typ=procsym then
  510. begin
  511. readprocdef.returndef:=p.propdef;
  512. { Insert hidden parameters }
  513. if assigned(astruct) then
  514. handle_calling_convention(readprocdef,hcc_default_actions_intf_struct)
  515. else
  516. handle_calling_convention(readprocdef,hcc_default_actions_intf);
  517. end;
  518. p.add_getter_or_setter_for_sym(palt_read,sym,def,readprocdef);
  519. end;
  520. end
  521. else
  522. p.inherit_accessor(palt_read);
  523. if try_to_consume(_WRITE) then
  524. begin
  525. gotreadorwrite:=true;
  526. p.propaccesslist[palt_write].clear;
  527. if parse_symlist(p.propaccesslist[palt_write],def) then
  528. begin
  529. sym:=p.propaccesslist[palt_write].firstsym^.sym;
  530. if sym.typ=procsym then
  531. begin
  532. { settter is a procedure with an extra value parameter
  533. of the of the property }
  534. writeprocdef.returndef:=voidtype;
  535. inc(paranr);
  536. hparavs:=cparavarsym.create('$value',10*paranr,vs_value,p.propdef,[]);
  537. writeprocdef.parast.insertsym(hparavs);
  538. { Insert hidden parameters }
  539. if not assigned(astruct) then
  540. handle_calling_convention(writeprocdef,hcc_default_actions_intf)
  541. else
  542. handle_calling_convention(writeprocdef,hcc_default_actions_intf_struct);
  543. end;
  544. p.add_getter_or_setter_for_sym(palt_write,sym,def,writeprocdef);
  545. end;
  546. end
  547. else
  548. p.inherit_accessor(palt_write);
  549. { a new property (needs to declare a getter or setter, except in
  550. an interface }
  551. if not(ppo_overrides in p.propoptions) and
  552. not is_interface(astruct) and
  553. not gotreadorwrite then
  554. Consume(_READ);
  555. end
  556. else
  557. parse_dispinterface(p,readprocdef,writeprocdef,paranr);
  558. { stored is not allowed for dispinterfaces, records or class properties }
  559. if assigned(astruct) and not(is_dispinterface(astruct) or is_record(astruct)) and not is_classproperty then
  560. begin
  561. { ppo_stored is default on for not overridden properties }
  562. if not assigned(p.overriddenpropsym) then
  563. include(p.propoptions,ppo_stored);
  564. if try_to_consume(_STORED) then
  565. begin
  566. include(p.propoptions,ppo_stored);
  567. p.propaccesslist[palt_stored].clear;
  568. if token=_ID then
  569. begin
  570. { in the case that idtoken=_DEFAULT }
  571. { we have to do nothing except }
  572. { setting ppo_stored, it's the same }
  573. { as stored true }
  574. if idtoken<>_DEFAULT then
  575. begin
  576. { parse_symlist cannot deal with constsyms, and
  577. we also don't want to put constsyms in symlists
  578. since they have to be evaluated immediately rather
  579. than each time the property is accessed
  580. The proper fix would be to always create a parse tree
  581. and then convert that one, if appropriate, to a symlist.
  582. Currently, we e.g. don't support any constant expressions
  583. yet either here, while Delphi does.
  584. }
  585. { make sure we don't let constants mask class fields/
  586. methods
  587. }
  588. sym:=nil;
  589. if (not assigned(astruct) or
  590. (search_struct_member(astruct,pattern)=nil)) and
  591. searchsym(pattern,sym,srsymtable) and
  592. (sym.typ = constsym) then
  593. begin
  594. addsymref(sym);
  595. if not is_boolean(tconstsym(sym).constdef) then
  596. Message(parser_e_stored_property_must_be_boolean)
  597. else if (tconstsym(sym).value.valueord=0) then
  598. { same as for _FALSE }
  599. exclude(p.propoptions,ppo_stored)
  600. else
  601. begin
  602. { same as for _TRUE }
  603. { do nothing - ppo_stored is already set to p.propoptions in "include(p.propoptions,ppo_stored);" above }
  604. { especially do not reset the default value - the stored specifier is independent on the default value! }
  605. end;
  606. consume(_ID);
  607. end
  608. else if parse_symlist(p.propaccesslist[palt_stored],def) then
  609. begin
  610. sym:=p.propaccesslist[palt_stored].firstsym^.sym;
  611. case sym.typ of
  612. procsym :
  613. begin
  614. { Create a temporary procvardef to handle parameters }
  615. storedprocdef:=cprocvardef.create(normal_function_level,true);
  616. include(storedprocdef.procoptions,po_methodpointer);
  617. { Return type must be boolean }
  618. storedprocdef.returndef:=pasbool1type;
  619. { Add index parameter if needed }
  620. if ppo_indexed in p.propoptions then
  621. begin
  622. hparavs:=cparavarsym.create('$index',10,vs_value,p.indexdef,[]);
  623. storedprocdef.parast.insertsym(hparavs);
  624. end;
  625. { Insert hidden parameters }
  626. if not assigned(astruct) then
  627. handle_calling_convention(storedprocdef,hcc_default_actions_intf)
  628. else
  629. handle_calling_convention(storedprocdef,hcc_default_actions_intf_struct);
  630. p.propaccesslist[palt_stored].procdef:=Tprocsym(sym).Find_procdef_bypara(storedprocdef.paras,storedprocdef.returndef,[cpo_allowdefaults,cpo_ignorehidden]);
  631. if not assigned(p.propaccesslist[palt_stored].procdef) then
  632. message(parser_e_ill_property_storage_sym);
  633. { Not needed anymore }
  634. storedprocdef.owner.deletedef(storedprocdef);
  635. end;
  636. fieldvarsym :
  637. begin
  638. if not assigned(def) then
  639. internalerror(200310073);
  640. if (ppo_hasparameters in p.propoptions) or
  641. not(is_boolean(def)) then
  642. Message(parser_e_stored_property_must_be_boolean);
  643. end;
  644. else
  645. Message(parser_e_ill_property_access_sym);
  646. end;
  647. end;
  648. end;
  649. end;
  650. end;
  651. end;
  652. if has_implicit_default(p) and not assigned(p.overriddenpropsym) then
  653. begin
  654. p.default:=0;
  655. end;
  656. if not is_record(astruct) and try_to_consume(_DEFAULT) then
  657. begin
  658. if not allow_default_property(p) then
  659. begin
  660. Message(parser_e_property_cant_have_a_default_value);
  661. { Error recovery }
  662. pt:=comp_expr([ef_accept_equal]);
  663. pt.free;
  664. end
  665. else
  666. begin
  667. { Get the result of the default, the firstpass is
  668. needed to support values like -1 }
  669. pt:=comp_expr([ef_accept_equal]);
  670. if (p.propdef.typ=setdef) and
  671. (pt.nodetype=arrayconstructorn) then
  672. begin
  673. arrayconstructor_to_set(pt);
  674. do_typecheckpass(pt);
  675. end;
  676. inserttypeconv(pt,p.propdef);
  677. if not(is_constnode(pt)) then
  678. Message(parser_e_property_default_value_must_const);
  679. { Set default value }
  680. case pt.nodetype of
  681. setconstn :
  682. p.default:=plongint(tsetconstnode(pt).value_set)^;
  683. ordconstn :
  684. if (Tordconstnode(pt).value<int64(low(longint))) or
  685. (Tordconstnode(pt).value>int64(high(cardinal))) then
  686. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(longint)),tostr(high(cardinal)))
  687. else
  688. p.default:=longint(tordconstnode(pt).value.svalue);
  689. niln :
  690. p.default:=0;
  691. realconstn:
  692. p.default:=longint(single(trealconstnode(pt).value_real));
  693. else if not codegenerror then
  694. internalerror(2019050525);
  695. end;
  696. pt.free;
  697. end;
  698. end
  699. else if not is_record(astruct) and try_to_consume(_NODEFAULT) then
  700. begin
  701. p.default:=longint($80000000);
  702. end;
  703. (*
  704. else {if allow_default_property(p) then
  705. begin
  706. p.default:=longint($80000000);
  707. end;
  708. *)
  709. { Parse possible "implements" keyword }
  710. if not is_record(astruct) and try_to_consume(_IMPLEMENTS) then
  711. repeat
  712. single_type(def,[]);
  713. if not(is_interface(def)) then
  714. message(parser_e_class_implements_must_be_interface);
  715. if is_interface(p.propdef) then
  716. begin
  717. { an interface type may delegate itself or one of its ancestors }
  718. if not def_is_related(p.propdef,def) then
  719. begin
  720. message2(parser_e_implements_must_have_correct_type,def.typename,p.propdef.typename);
  721. exit;
  722. end;
  723. end
  724. else if is_class(p.propdef) then
  725. begin
  726. ImplIntf:=find_implemented_interface(tobjectdef(p.propdef),tobjectdef(def));
  727. if assigned(ImplIntf) then
  728. begin
  729. if compare_defs(ImplIntf.IntfDef,def,nothingn)<te_equal then
  730. begin
  731. message2(parser_e_implements_must_have_correct_type,ImplIntf.IntfDef.typename,def.typename);
  732. exit;
  733. end;
  734. end
  735. else
  736. begin
  737. message2(parser_e_class_doesnt_implement_interface,p.propdef.typename,def.typename);
  738. exit;
  739. end;
  740. end
  741. else
  742. begin
  743. message(parser_e_implements_must_be_class_or_interface);
  744. exit;
  745. end;
  746. if not assigned(p.propaccesslist[palt_read].firstsym) then
  747. begin
  748. message(parser_e_implements_must_read_specifier);
  749. exit;
  750. end;
  751. if assigned(p.propaccesslist[palt_read].procdef) and
  752. (tprocdef(p.propaccesslist[palt_read].procdef).proccalloption<>pocall_default) then
  753. message(parser_e_implements_getter_not_default_cc);
  754. if assigned(p.propaccesslist[palt_write].firstsym) then
  755. begin
  756. message(parser_e_implements_must_not_have_write_specifier);
  757. exit;
  758. end;
  759. if assigned(p.propaccesslist[palt_stored].firstsym) then
  760. begin
  761. message(parser_e_implements_must_not_have_stored_specifier);
  762. exit;
  763. end;
  764. found:=false;
  765. ImplIntf:=nil;
  766. for i:=0 to tobjectdef(astruct).ImplementedInterfaces.Count-1 do
  767. begin
  768. ImplIntf:=TImplementedInterface(tobjectdef(astruct).ImplementedInterfaces[i]);
  769. if compare_defs(def,ImplIntf.IntfDef,nothingn)>=te_equal then
  770. begin
  771. found:=true;
  772. break;
  773. end;
  774. end;
  775. if found then
  776. begin
  777. { An interface may not be delegated by more than one property,
  778. it also may not have method mappings. }
  779. if Assigned(ImplIntf.ImplementsGetter) then
  780. message1(parser_e_duplicate_implements_clause,ImplIntf.IntfDef.typename);
  781. if Assigned(ImplIntf.NameMappings) then
  782. message2(parser_e_mapping_no_implements,ImplIntf.IntfDef.typename,astruct.objrealname^);
  783. ImplIntf.ImplementsGetter:=p;
  784. ImplIntf.VtblImplIntf:=ImplIntf;
  785. case p.propaccesslist[palt_read].firstsym^.sym.typ of
  786. procsym :
  787. begin
  788. if (po_virtualmethod in tprocdef(p.propaccesslist[palt_read].procdef).procoptions) and
  789. not is_objectpascal_helper(tprocdef(p.propaccesslist[palt_read].procdef).struct) then
  790. ImplIntf.IType:=etVirtualMethodResult
  791. else
  792. ImplIntf.IType:=etStaticMethodResult;
  793. end;
  794. fieldvarsym :
  795. begin
  796. ImplIntf.IType:=etFieldValue;
  797. { this must be done in a more robust way. Can't read the
  798. fieldvarsym's fieldoffset yet, because it may not yet
  799. be set }
  800. ImplIntf.ImplementsField:=p.propaccesslist[palt_read].firstsym^.sym;
  801. end
  802. else
  803. internalerror(200802161);
  804. end;
  805. if not is_interface(p.propdef) then
  806. case ImplIntf.IType of
  807. etVirtualMethodResult: ImplIntf.IType := etVirtualMethodClass;
  808. etStaticMethodResult: ImplIntf.IType := etStaticMethodClass;
  809. etFieldValue: ImplIntf.IType := etFieldValueClass;
  810. else
  811. internalerror(200912101);
  812. end;
  813. end
  814. else
  815. message1(parser_e_implements_uses_non_implemented_interface,def.typename);
  816. until not try_to_consume(_COMMA);
  817. { register propgetter and propsetter procdefs }
  818. if assigned(current_module) and current_module.in_interface then
  819. begin
  820. if readprocdef.proctypeoption=potype_propgetter then
  821. readprocdef.register_def
  822. else
  823. readprocdef.free;
  824. if writeprocdef.proctypeoption=potype_propsetter then
  825. writeprocdef.register_def
  826. else
  827. writeprocdef.free;
  828. end
  829. else
  830. begin
  831. if readprocdef.proctypeoption=potype_propgetter then
  832. readprocdef.maybe_put_in_symtable_stack
  833. else
  834. readprocdef.free;
  835. if writeprocdef.proctypeoption=potype_propsetter then
  836. writeprocdef.maybe_put_in_symtable_stack
  837. else
  838. writeprocdef.free;
  839. end;
  840. result:=p;
  841. end;
  842. function maybe_parse_proc_directives(def:tdef):boolean;
  843. begin
  844. result:=false;
  845. { Process procvar directives before = and ; }
  846. if (
  847. (def.typ=procvardef) or
  848. is_funcref(def)
  849. ) and
  850. (def.typesym=nil) and
  851. check_proc_directive(true) then
  852. begin
  853. parse_proctype_directives(def);
  854. result:=true;
  855. end;
  856. end;
  857. const
  858. variantrecordlevel : longint = 0;
  859. procedure read_public_and_external_sc(sc:TFPObjectList);
  860. var
  861. vs: tabstractvarsym;
  862. begin
  863. { only allowed for one var }
  864. vs:=tabstractvarsym(sc[0]);
  865. if sc.count>1 then
  866. Message1(parser_e_directive_only_one_var,arraytokeninfo[idtoken].str);
  867. read_public_and_external(vs);
  868. end;
  869. procedure read_public_and_external(vs: tabstractvarsym);
  870. var
  871. is_dll,
  872. is_far,
  873. is_cdecl,
  874. is_external_var,
  875. is_weak_external,
  876. is_public_var : boolean;
  877. dll_name,section_name,
  878. C_name,mangledname : string;
  879. begin
  880. { only allowed for one var }
  881. { only allow external and public on global symbols }
  882. if vs.typ<>staticvarsym then
  883. begin
  884. Message(parser_e_no_local_var_external);
  885. exit;
  886. end;
  887. { defaults }
  888. is_dll:=false;
  889. is_far:=false;
  890. is_cdecl:=false;
  891. is_external_var:=false;
  892. is_public_var:=false;
  893. section_name := '';
  894. dll_name := '';
  895. C_name:=vs.realname;
  896. { macpas specific handling due to some switches}
  897. if (m_mac in current_settings.modeswitches) then
  898. begin
  899. if (cs_external_var in current_settings.localswitches) then
  900. begin {The effect of this is the same as if cvar; external; has been given as directives.}
  901. is_cdecl:=true;
  902. is_external_var:=true;
  903. end
  904. else if (cs_externally_visible in current_settings.localswitches) then
  905. begin {The effect of this is the same as if cvar has been given as directives and it's made public.}
  906. is_cdecl:=true;
  907. is_public_var:=true;
  908. end;
  909. end;
  910. { cdecl }
  911. if try_to_consume(_CVAR) then
  912. begin
  913. consume(_SEMICOLON);
  914. is_cdecl:=true;
  915. end;
  916. { external }
  917. is_weak_external:=try_to_consume(_WEAKEXTERNAL);
  918. if is_weak_external or
  919. try_to_consume(_EXTERNAL) then
  920. begin
  921. is_external_var:=true;
  922. { near/far? }
  923. if target_info.system in systems_allow_external_far_var then
  924. begin
  925. if try_to_consume(_FAR) then
  926. is_far:=true
  927. else if try_to_consume(_NEAR) then
  928. is_far:=false;
  929. end;
  930. if (idtoken<>_NAME) and (token<>_SEMICOLON) then
  931. begin
  932. is_dll:=true;
  933. dll_name:=get_stringconst;
  934. if ExtractFileExt(dll_name)='' then
  935. dll_name:=ChangeFileExt(dll_name,target_info.sharedlibext);
  936. end;
  937. if not(is_cdecl) and try_to_consume(_NAME) then
  938. C_name:=get_stringconst;
  939. consume(_SEMICOLON);
  940. end;
  941. { export or public }
  942. if idtoken in [_EXPORT,_PUBLIC] then
  943. begin
  944. consume(_ID);
  945. if is_external_var then
  946. Message(parser_e_not_external_and_export)
  947. else
  948. is_public_var:=true;
  949. if try_to_consume(_NAME) then
  950. C_name:=get_stringconst;
  951. if (target_info.system in systems_allow_section_no_semicolon) and
  952. (vs.typ=staticvarsym) and
  953. try_to_consume (_SECTION) then
  954. section_name:=get_stringconst;
  955. consume(_SEMICOLON);
  956. end;
  957. { Windows uses an indirect reference using import tables }
  958. if is_dll and
  959. (target_info.system in systems_all_windows) then
  960. include(vs.varoptions,vo_is_dll_var);
  961. { This can only happen if vs.typ=staticvarsym }
  962. if section_name<>'' then
  963. begin
  964. tstaticvarsym(vs).section:=section_name;
  965. include(vs.varoptions,vo_has_section);
  966. end;
  967. { Add C _ prefix }
  968. if is_cdecl or
  969. (
  970. is_dll and
  971. (target_info.system in systems_darwin)
  972. ) then
  973. C_Name := target_info.Cprefix+C_Name;
  974. if is_public_var then
  975. begin
  976. include(vs.varoptions,vo_is_public);
  977. vs.varregable := vr_none;
  978. { mark as referenced }
  979. inc(vs.refs);
  980. end;
  981. mangledname:=C_name;
  982. { now we can insert it in the import lib if its a dll, or
  983. add it to the externals }
  984. if is_external_var then
  985. begin
  986. if vo_is_typed_const in vs.varoptions then
  987. Message(parser_e_initialized_not_for_external);
  988. include(vs.varoptions,vo_is_external);
  989. if is_far then
  990. include(vs.varoptions,vo_is_far);
  991. if (is_weak_external) then
  992. begin
  993. if not(target_info.system in systems_weak_linking) then
  994. message(parser_e_weak_external_not_supported);
  995. include(vs.varoptions,vo_is_weak_external);
  996. end;
  997. vs.varregable := vr_none;
  998. if is_dll then
  999. begin
  1000. if target_info.system in (systems_all_windows + systems_nativent +
  1001. [system_i386_emx, system_i386_os2]) then
  1002. mangledname:=make_dllmangledname(dll_name,C_name,0,pocall_none);
  1003. current_module.AddExternalImport(dll_name,C_Name,mangledname,0,true,false);
  1004. end
  1005. else
  1006. if tf_has_dllscanner in target_info.flags then
  1007. current_module.dllscannerinputlist.Add(vs.mangledname,vs);
  1008. end;
  1009. { Set the assembler name }
  1010. tstaticvarsym(vs).set_mangledbasename(mangledname);
  1011. tstaticvarsym(vs).set_mangledname(mangledname);
  1012. end;
  1013. procedure try_consume_sectiondirective(var asection: ansistring);
  1014. begin
  1015. if idtoken=_SECTION then
  1016. begin
  1017. consume(_ID);
  1018. asection:=get_stringconst;
  1019. consume(_SEMICOLON);
  1020. end;
  1021. end;
  1022. procedure try_read_field_external(vs: tabstractvarsym);
  1023. var
  1024. extname: string;
  1025. begin
  1026. if try_to_consume(_EXTERNAL) then
  1027. begin
  1028. consume(_NAME);
  1029. extname:=get_stringconst;
  1030. tfieldvarsym(vs).set_externalname(extname);
  1031. consume(_SEMICOLON);
  1032. end;
  1033. end;
  1034. procedure try_read_field_external_sc(sc:TFPObjectList);
  1035. var
  1036. vs: tabstractvarsym;
  1037. begin
  1038. { only allowed for one var }
  1039. vs:=tabstractvarsym(sc[0]);
  1040. if sc.count>1 then
  1041. Message1(parser_e_directive_only_one_var,arraytokeninfo[idtoken].str);
  1042. try_read_field_external(vs);
  1043. end;
  1044. procedure read_var_decls(options:Tvar_dec_options;out had_generic:boolean);
  1045. procedure read_default_value(sc : TFPObjectList);
  1046. var
  1047. vs : tabstractnormalvarsym;
  1048. tcsym : tstaticvarsym;
  1049. templist : tasmlist;
  1050. begin
  1051. vs:=tabstractnormalvarsym(sc[0]);
  1052. if sc.count>1 then
  1053. Message(parser_e_initialized_only_one_var);
  1054. if vo_is_thread_var in vs.varoptions then
  1055. Message(parser_e_initialized_not_for_threadvar);
  1056. consume(_EQ);
  1057. case vs.typ of
  1058. localvarsym :
  1059. begin
  1060. tcsym:=cstaticvarsym.create('$default'+vs.realname,vs_const,vs.vardef,[]);
  1061. include(tcsym.symoptions,sp_internal);
  1062. symtablestack.top.insertsym(tcsym);
  1063. templist:=tasmlist.create;
  1064. read_typed_const(templist,tcsym,false);
  1065. { in case of a generic routine, this initialisation value is not
  1066. used, and will be re-parsed during specialisations (and the
  1067. current version is not type-correct and hence breaks code
  1068. generation for LLVM) }
  1069. if not parse_generic then
  1070. begin
  1071. vs.defaultconstsym:=tcsym;
  1072. current_asmdata.asmlists[al_typedconsts].concatlist(templist);
  1073. end;
  1074. templist.free;
  1075. end;
  1076. staticvarsym :
  1077. begin
  1078. maybe_guarantee_record_typesym(vs.vardef,vs.vardef.owner);
  1079. read_typed_const(current_asmdata.asmlists[al_typedconsts],tstaticvarsym(vs),false);
  1080. end;
  1081. else
  1082. internalerror(200611051);
  1083. end;
  1084. vs.varstate:=vs_initialised;
  1085. end;
  1086. {$ifdef gpc_mode}
  1087. procedure read_gpc_name(sc : TFPObjectList);
  1088. var
  1089. vs : tabstractnormalvarsym;
  1090. C_Name : string;
  1091. begin
  1092. consume(_ID);
  1093. C_Name:=get_stringconst;
  1094. vs:=tabstractnormalvarsym(sc[0]);
  1095. if sc.count>1 then
  1096. Message(parser_e_directive_only_one_var,'ABSOLUTE');
  1097. if vs.typ=staticvarsym then
  1098. begin
  1099. tstaticvarsym(vs).set_mangledname(C_Name);
  1100. include(vs.varoptions,vo_is_external);
  1101. end
  1102. else
  1103. Message(parser_e_no_local_var_external);
  1104. end;
  1105. {$endif}
  1106. procedure read_absolute(sc : TFPObjectList);
  1107. var
  1108. vs : tabstractvarsym;
  1109. abssym : tabsolutevarsym;
  1110. pt,hp : tnode;
  1111. st : tsymtable;
  1112. {$if defined(i386) or defined(i8086)}
  1113. tmpaddr : int64;
  1114. {$endif defined(i386) or defined(i8086)}
  1115. begin
  1116. abssym:=nil;
  1117. { only allowed for one var }
  1118. vs:=tabstractvarsym(sc[0]);
  1119. if sc.count>1 then
  1120. Message1(parser_e_directive_only_one_var,'ABSOLUTE');
  1121. if vo_is_typed_const in vs.varoptions then
  1122. Message(parser_e_initialized_not_for_external);
  1123. { parse the rest }
  1124. pt:=expr(true);
  1125. { check allowed absolute types }
  1126. if (pt.nodetype=stringconstn) or
  1127. (is_constcharnode(pt)) then
  1128. begin
  1129. abssym:=cabsolutevarsym.create(vs.realname,vs.vardef);
  1130. abssym.fileinfo:=vs.fileinfo;
  1131. if pt.nodetype=stringconstn then
  1132. abssym.asmname:=stringdup(tstringconstnode(pt).asrawbytestring)
  1133. else
  1134. abssym.asmname:=stringdup(chr(tordconstnode(pt).value.svalue));
  1135. abssym.abstyp:=toasm;
  1136. end
  1137. { address }
  1138. else if is_constintnode(pt) then
  1139. begin
  1140. abssym:=cabsolutevarsym.create(vs.realname,vs.vardef);
  1141. abssym.fileinfo:=vs.fileinfo;
  1142. abssym.abstyp:=toaddr;
  1143. {$ifndef cpu64bitaddr}
  1144. { on 64 bit systems, abssym.addroffset is a qword and hence this
  1145. test is useless (value is a 64 bit entity) and will always fail
  1146. for positive values (since int64(high(abssym.addroffset))=-1
  1147. }
  1148. if (Tordconstnode(pt).value<int64(low(abssym.addroffset))) or
  1149. (Tordconstnode(pt).value>int64(high(abssym.addroffset))) then
  1150. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(abssym.addroffset)),tostr(high(abssym.addroffset)))
  1151. else
  1152. {$endif}
  1153. abssym.addroffset:=Tordconstnode(pt).value.svalue;
  1154. {$if defined(i386) or defined(i8086)}
  1155. tcpuabsolutevarsym(abssym).absseg:=false;
  1156. if (target_info.system in [system_i386_go32v2,system_i386_watcom,system_i8086_msdos,system_i8086_win16,system_i8086_embedded]) and
  1157. try_to_consume(_COLON) then
  1158. begin
  1159. pt.free;
  1160. pt:=expr(true);
  1161. if is_constintnode(pt) then
  1162. begin
  1163. {$if defined(i8086)}
  1164. tcpuabsolutevarsym(abssym).addrsegment:=abssym.addroffset;
  1165. tmpaddr:=tordconstnode(pt).value.svalue;
  1166. if (tmpaddr<int64(low(abssym.addroffset))) or
  1167. (tmpaddr>int64(high(abssym.addroffset))) then
  1168. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(abssym.addroffset)),tostr(high(abssym.addroffset)))
  1169. else
  1170. abssym.addroffset:=tmpaddr;
  1171. {$elseif defined(i386)}
  1172. tmpaddr:=abssym.addroffset shl 4+tordconstnode(pt).value.svalue;
  1173. if (tmpaddr<int64(low(abssym.addroffset))) or
  1174. (tmpaddr>int64(high(abssym.addroffset))) then
  1175. message3(type_e_range_check_error_bounds,tostr(Tordconstnode(pt).value),tostr(low(abssym.addroffset)),tostr(high(abssym.addroffset)))
  1176. else
  1177. abssym.addroffset:=tmpaddr;
  1178. {$endif}
  1179. tcpuabsolutevarsym(abssym).absseg:=true;
  1180. end
  1181. else
  1182. Message(type_e_ordinal_expr_expected);
  1183. end;
  1184. {$endif i386 or i8086}
  1185. end
  1186. { variable }
  1187. else
  1188. begin
  1189. { we have to be able to take the address of the absolute
  1190. expression
  1191. }
  1192. valid_for_addr(pt,true);
  1193. { remove subscriptn before checking for loadn }
  1194. hp:=pt;
  1195. while (hp.nodetype in [subscriptn,typeconvn,vecn]) do
  1196. begin
  1197. { check for implicit dereferencing and reject it }
  1198. if (hp.nodetype in [subscriptn,vecn]) then
  1199. begin
  1200. if (tunarynode(hp).left.resultdef.typ in [pointerdef,classrefdef]) then
  1201. break;
  1202. { catch, e.g., 'var b: char absolute pchar_var[5];"
  1203. (pchar_var[5] is a pchar_2_string typeconv ->
  1204. the vecn only sees an array of char)
  1205. I don't know if all of these type conversions are
  1206. possible, but they're definitely all bad.
  1207. }
  1208. if (tunarynode(hp).left.nodetype=typeconvn) and
  1209. (ttypeconvnode(tunarynode(hp).left).convtype in
  1210. [tc_pchar_2_string,tc_pointer_2_array,
  1211. tc_intf_2_string,tc_intf_2_guid,
  1212. tc_dynarray_2_variant,tc_interface_2_variant,
  1213. tc_array_2_dynarray]) then
  1214. break;
  1215. if (tunarynode(hp).left.resultdef.typ=stringdef) and
  1216. not(tstringdef(tunarynode(hp).left.resultdef).stringtype in [st_shortstring,st_longstring]) then
  1217. break;
  1218. if (tunarynode(hp).left.resultdef.typ=objectdef) and
  1219. (tobjectdef(tunarynode(hp).left.resultdef).objecttype<>odt_object) then
  1220. break;
  1221. if is_dynamic_array(tunarynode(hp).left.resultdef) then
  1222. break;
  1223. end;
  1224. hp:=tunarynode(hp).left;
  1225. end;
  1226. if (hp.nodetype=loadn) then
  1227. begin
  1228. { we should check the result type of loadn }
  1229. if not (tloadnode(hp).symtableentry.typ in [fieldvarsym,staticvarsym,localvarsym,paravarsym,absolutevarsym]) then
  1230. Message(parser_e_absolute_only_to_var_or_const);
  1231. if vs=tloadnode(hp).symtableentry then
  1232. Message(parser_e_absolute_sym_cannot_reference_itself)
  1233. else
  1234. begin
  1235. abssym:=cabsolutevarsym.create(vs.realname,vs.vardef);
  1236. abssym.fileinfo:=vs.fileinfo;
  1237. abssym.abstyp:=tovar;
  1238. abssym.ref:=node_to_propaccesslist(pt);
  1239. end;
  1240. { if the sizes are different, can't be a regvar since you }
  1241. { can't be "absolute upper 8 bits of a register" (except }
  1242. { if its a record field of the same size of a record }
  1243. { regvar, but in that case pt.resultdef.size will have }
  1244. { the same size since it refers to the field and not to }
  1245. { the whole record -- which is why we use pt and not hp) }
  1246. { we can't take the size of an open array }
  1247. if is_open_array(pt.resultdef) or
  1248. (vs.vardef.size <> pt.resultdef.size) then
  1249. make_not_regable(pt,[ra_addr_regable]);
  1250. end
  1251. else
  1252. Message(parser_e_absolute_only_to_var_or_const);
  1253. end;
  1254. pt.free;
  1255. { replace old varsym with the new absolutevarsym }
  1256. if assigned(abssym) then
  1257. begin
  1258. st:=vs.owner;
  1259. vs.owner.Deletesym(vs);
  1260. st.insertsym(abssym);
  1261. sc[0]:=abssym;
  1262. end;
  1263. end;
  1264. var
  1265. sc : TFPObjectList;
  1266. vs : tabstractvarsym;
  1267. hdef : tdef;
  1268. i : longint;
  1269. flags : thccflags;
  1270. first,
  1271. isgeneric,
  1272. semicoloneaten,
  1273. allowdefaultvalue,
  1274. hasdefaultvalue : boolean;
  1275. hintsymoptions : tsymoptions;
  1276. deprecatedmsg : pshortstring;
  1277. old_block_type : tblock_type;
  1278. sectionname : ansistring;
  1279. typepos,
  1280. tmp_filepos,
  1281. old_current_filepos : tfileposinfo;
  1282. begin
  1283. old_block_type:=block_type;
  1284. block_type:=bt_var;
  1285. { Force an expected ID error message }
  1286. if not (token in [_ID,_CASE,_END]) then
  1287. consume(_ID);
  1288. { read vars }
  1289. sc:=TFPObjectList.create(false);
  1290. first:=true;
  1291. had_generic:=false;
  1292. vs:=nil;
  1293. fillchar(tmp_filepos,sizeof(tmp_filepos),0);
  1294. while (token=_ID) do
  1295. begin
  1296. semicoloneaten:=false;
  1297. hasdefaultvalue:=false;
  1298. allowdefaultvalue:=true;
  1299. sc.clear;
  1300. repeat
  1301. if (token = _ID) then
  1302. begin
  1303. isgeneric:=(vd_check_generic in options) and
  1304. not (m_delphi in current_settings.modeswitches) and
  1305. (idtoken=_GENERIC);
  1306. case symtablestack.top.symtabletype of
  1307. localsymtable :
  1308. vs:=clocalvarsym.create(orgpattern,vs_value,generrordef,[]);
  1309. staticsymtable,
  1310. globalsymtable :
  1311. begin
  1312. vs:=cstaticvarsym.create(orgpattern,vs_value,generrordef,[]);
  1313. if vd_threadvar in options then
  1314. include(vs.varoptions,vo_is_thread_var);
  1315. end;
  1316. else
  1317. internalerror(200411064);
  1318. end;
  1319. sc.add(vs);
  1320. if isgeneric then
  1321. tmp_filepos:=current_filepos;
  1322. end
  1323. else
  1324. isgeneric:=false;
  1325. consume(_ID);
  1326. { when the first variable had been read the next declaration could be
  1327. a "generic procedure", "generic function" or
  1328. "generic class (function/procedure)" }
  1329. if not first
  1330. and isgeneric
  1331. and (sc.count=1)
  1332. and (token in [_PROCEDURE,_FUNCTION,_CLASS]) then
  1333. begin
  1334. vs.free;
  1335. sc.clear;
  1336. had_generic:=true;
  1337. break;
  1338. end
  1339. else
  1340. begin
  1341. vs.register_sym;
  1342. if isgeneric then
  1343. begin
  1344. { ensure correct error position }
  1345. old_current_filepos:=current_filepos;
  1346. current_filepos:=tmp_filepos;
  1347. symtablestack.top.insertsym(vs);
  1348. current_filepos:=old_current_filepos;
  1349. end
  1350. else
  1351. symtablestack.top.insertsym(vs);
  1352. end;
  1353. until not try_to_consume(_COMMA);
  1354. if had_generic then
  1355. break;
  1356. { read variable type def }
  1357. block_type:=bt_var_type;
  1358. consume(_COLON);
  1359. typepos:=current_tokenpos;
  1360. {$ifdef gpc_mode}
  1361. if (m_gpc in current_settings.modeswitches) and
  1362. (token=_ID) and
  1363. (orgpattern='__asmname__') then
  1364. read_gpc_name(sc);
  1365. {$endif}
  1366. read_anon_type(hdef,false,nil);
  1367. maybe_guarantee_record_typesym(hdef,symtablestack.top);
  1368. for i:=0 to sc.count-1 do
  1369. begin
  1370. vs:=tabstractvarsym(sc[i]);
  1371. vs.vardef:=hdef;
  1372. end;
  1373. block_type:=bt_var;
  1374. { Process procvar directives }
  1375. if maybe_parse_proc_directives(hdef) then
  1376. semicoloneaten:=true;
  1377. { check for absolute }
  1378. if try_to_consume(_ABSOLUTE) then
  1379. begin
  1380. read_absolute(sc);
  1381. allowdefaultvalue:=false;
  1382. end;
  1383. { Check for EXTERNAL etc directives before a semicolon }
  1384. if (idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR]) or (idtoken = _WEAKEXTERNAL) then
  1385. begin
  1386. read_public_and_external_sc(sc);
  1387. allowdefaultvalue:=false;
  1388. semicoloneaten:=true;
  1389. end;
  1390. { try to parse the hint directives }
  1391. hintsymoptions:=[];
  1392. deprecatedmsg:=nil;
  1393. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1394. for i:=0 to sc.count-1 do
  1395. begin
  1396. vs:=tabstractvarsym(sc[i]);
  1397. vs.symoptions := vs.symoptions + hintsymoptions;
  1398. if deprecatedmsg<>nil then
  1399. vs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1400. end;
  1401. stringdispose(deprecatedmsg);
  1402. { Handling of Delphi typed const = initialized vars }
  1403. if allowdefaultvalue and
  1404. (token=_EQ) and
  1405. not(m_tp7 in current_settings.modeswitches) and
  1406. (symtablestack.top.symtabletype<>parasymtable) then
  1407. begin
  1408. { Add calling convention for procvar }
  1409. if (
  1410. (hdef.typ=procvardef) or
  1411. is_funcref(hdef)
  1412. ) and
  1413. (hdef.typesym=nil) then
  1414. begin
  1415. if po_is_function_ref in tprocvardef(hdef).procoptions then
  1416. begin
  1417. if not (m_function_references in current_settings.modeswitches) and
  1418. not (po_is_block in tprocvardef(hdef).procoptions) then
  1419. messagepos(typepos,sym_e_error_in_type_def)
  1420. else
  1421. begin
  1422. if adjust_funcref(hdef,nil,nil) then
  1423. { the def was changed, so update it }
  1424. for i:=0 to sc.count-1 do
  1425. begin
  1426. vs:=tabstractvarsym(sc[i]);
  1427. vs.vardef:=hdef;
  1428. end;
  1429. if current_scanner.replay_stack_depth=0 then
  1430. hdef.register_def;
  1431. end;
  1432. end;
  1433. handle_calling_convention(hdef,hcc_default_actions_intf);
  1434. end;
  1435. read_default_value(sc);
  1436. hasdefaultvalue:=true;
  1437. end
  1438. else
  1439. begin
  1440. if not(semicoloneaten) then
  1441. consume(_SEMICOLON);
  1442. end;
  1443. { Support calling convention for procvars after semicolon }
  1444. if not(hasdefaultvalue) and
  1445. (
  1446. (hdef.typ=procvardef) or
  1447. is_funcref(hdef)
  1448. ) and
  1449. (hdef.typesym=nil) then
  1450. begin
  1451. { Parse procvar directives after ; }
  1452. maybe_parse_proc_directives(hdef);
  1453. if (hdef.typ=procvardef) and (po_is_function_ref in tprocvardef(hdef).procoptions) then
  1454. begin
  1455. if not (m_function_references in current_settings.modeswitches) and
  1456. not (po_is_block in tprocvardef(hdef).procoptions) then
  1457. messagepos(typepos,sym_e_error_in_type_def)
  1458. else
  1459. begin
  1460. if adjust_funcref(hdef,nil,nil) then
  1461. { the def was changed, so update it }
  1462. for i:=0 to sc.count-1 do
  1463. begin
  1464. vs:=tabstractvarsym(sc[i]);
  1465. vs.vardef:=hdef;
  1466. end;
  1467. if current_scanner.replay_stack_depth=0 then
  1468. hdef.register_def;
  1469. end;
  1470. end;
  1471. { Add calling convention for procvar }
  1472. if hdef.typ=procvardef then
  1473. flags:=hcc_default_actions_intf
  1474. else
  1475. flags:=hcc_default_actions_intf_struct;
  1476. handle_calling_convention(hdef,flags);
  1477. { Handling of Delphi typed const = initialized vars }
  1478. if (token=_EQ) and
  1479. not(m_tp7 in current_settings.modeswitches) and
  1480. (symtablestack.top.symtabletype<>parasymtable) then
  1481. begin
  1482. read_default_value(sc);
  1483. hasdefaultvalue:=true;
  1484. end;
  1485. end;
  1486. { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
  1487. if (
  1488. (
  1489. ((idtoken in [_EXPORT,_EXTERNAL,_PUBLIC,_CVAR]) or (idtoken = _WEAKEXTERNAL)) and
  1490. (m_cvar_support in current_settings.modeswitches)
  1491. ) or
  1492. (
  1493. (m_mac in current_settings.modeswitches) and
  1494. (
  1495. (cs_external_var in current_settings.localswitches) or
  1496. (cs_externally_visible in current_settings.localswitches)
  1497. )
  1498. )
  1499. ) then
  1500. read_public_and_external_sc(sc);
  1501. { try to parse a section directive }
  1502. if (target_info.system in systems_allow_section) and
  1503. (symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) and
  1504. (idtoken=_SECTION) then
  1505. begin
  1506. try_consume_sectiondirective(sectionname);
  1507. if sectionname<>'' then
  1508. begin
  1509. for i:=0 to sc.count-1 do
  1510. begin
  1511. vs:=tabstractvarsym(sc[i]);
  1512. if (vs.varoptions *[vo_is_external,vo_is_weak_external])<>[] then
  1513. Message(parser_e_externals_no_section);
  1514. if vs.typ<>staticvarsym then
  1515. Message(parser_e_section_no_locals);
  1516. tstaticvarsym(vs).section:=sectionname;
  1517. include(vs.varoptions, vo_has_section);
  1518. end;
  1519. end;
  1520. end;
  1521. { allocate normal variable (non-external and non-typed-const) staticvarsyms }
  1522. for i:=0 to sc.count-1 do
  1523. begin
  1524. vs:=tabstractvarsym(sc[i]);
  1525. if (vs.typ=staticvarsym) and
  1526. not(vo_is_typed_const in vs.varoptions) and
  1527. not(vo_is_external in vs.varoptions) then
  1528. cnodeutils.insertbssdata(tstaticvarsym(vs));
  1529. if vo_is_public in vs.varoptions then
  1530. current_module.add_public_asmsym(vs.mangledname,AB_GLOBAL,AT_DATA);
  1531. end;
  1532. first:=false;
  1533. end;
  1534. block_type:=old_block_type;
  1535. { free the list }
  1536. sc.free;
  1537. end;
  1538. function check_allowed_for_var_or_const(def:tdef;allowdynarray:boolean):boolean;
  1539. var
  1540. stowner,tmpdef : tdef;
  1541. st : tsymtable;
  1542. begin
  1543. result:=true;
  1544. st:=symtablestack.top;
  1545. if not (st.symtabletype in [recordsymtable,objectsymtable]) then
  1546. exit;
  1547. stowner:=tdef(st.defowner);
  1548. while assigned(stowner) and (stowner.typ in [objectdef,recorddef]) do
  1549. begin
  1550. if def.typ=arraydef then
  1551. begin
  1552. tmpdef:=def;
  1553. while (tmpdef.typ=arraydef) do
  1554. begin
  1555. { dynamic arrays are allowed in certain cases }
  1556. if allowdynarray and (ado_IsDynamicArray in tarraydef(tmpdef).arrayoptions) then
  1557. begin
  1558. tmpdef:=nil;
  1559. break;
  1560. end;
  1561. tmpdef:=tarraydef(tmpdef).elementdef;
  1562. end;
  1563. end
  1564. else
  1565. tmpdef:=def;
  1566. if assigned(tmpdef) and
  1567. (is_object(tmpdef) or is_record(tmpdef)) and
  1568. is_owned_by(tabstractrecorddef(stowner),tabstractrecorddef(tmpdef)) then
  1569. begin
  1570. Message1(type_e_type_is_not_completly_defined,tabstractrecorddef(tmpdef).RttiName);
  1571. result:=false;
  1572. break;
  1573. end;
  1574. stowner:=tdef(stowner.owner.defowner);
  1575. end;
  1576. end;
  1577. procedure read_record_fields(options:Tvar_dec_options; reorderlist: TFPObjectList; variantdesc : ppvariantrecdesc;out had_generic:boolean; out attr_element_count : integer);
  1578. var
  1579. sc : TFPObjectList;
  1580. i : longint;
  1581. hs,sorg : string;
  1582. gendef,hdef,casetype : tdef;
  1583. { maxsize contains the max. size of a variant }
  1584. { startvarrec contains the start of the variant part of a record }
  1585. maxsize, startvarrecsize : asizeint;
  1586. usedalign,
  1587. maxalignment,startvarrecalign,
  1588. maxpadalign, startpadalign: shortint;
  1589. pt : tnode;
  1590. fieldvs : tfieldvarsym;
  1591. hstaticvs : tstaticvarsym;
  1592. vs : tabstractvarsym;
  1593. srsym : tsym;
  1594. srsymtable : TSymtable;
  1595. visibility : tvisibility;
  1596. recst : tabstractrecordsymtable;
  1597. unionsymtable : trecordsymtable;
  1598. offset : longint;
  1599. uniondef : trecorddef;
  1600. hintsymoptions : tsymoptions;
  1601. deprecatedmsg : pshortstring;
  1602. hadgendummy,
  1603. semicoloneaten,
  1604. removeclassoption: boolean;
  1605. dummyattrelementcount : integer;
  1606. {$if defined(powerpc) or defined(powerpc64)}
  1607. tempdef: tdef;
  1608. is_first_type: boolean;
  1609. {$endif powerpc or powerpc64}
  1610. old_block_type: tblock_type;
  1611. typepos : tfileposinfo;
  1612. begin
  1613. old_block_type:=block_type;
  1614. block_type:=bt_var;
  1615. recst:=tabstractrecordsymtable(symtablestack.top);
  1616. {$if defined(powerpc) or defined(powerpc64)}
  1617. is_first_type:=true;
  1618. {$endif powerpc or powerpc64}
  1619. { Force an expected ID error message }
  1620. if not (token in [_ID,_CASE,_END]) then
  1621. consume(_ID);
  1622. { read vars }
  1623. sc:=TFPObjectList.create(false);
  1624. removeclassoption:=false;
  1625. had_generic:=false;
  1626. attr_element_count:=0;
  1627. while (token=_ID) and
  1628. not(((vd_object in options) or
  1629. ((vd_record in options) and (m_advanced_records in current_settings.modeswitches))) and
  1630. ((idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT]) or
  1631. ((m_final_fields in current_settings.modeswitches) and
  1632. (idtoken=_FINAL)))) do
  1633. begin
  1634. visibility:=symtablestack.top.currentvisibility;
  1635. semicoloneaten:=false;
  1636. sc.clear;
  1637. repeat
  1638. sorg:=orgpattern;
  1639. if token=_ID then
  1640. begin
  1641. vs:=cfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1642. { normally the visibility is set via addfield, but sometimes
  1643. we collect symbols so we can add them in a batch of
  1644. potentially mixed visibility, and then the individual
  1645. symbols need to have their visibility already set }
  1646. vs.visibility:=visibility;
  1647. if (vd_check_generic in options) and (idtoken=_GENERIC) then
  1648. had_generic:=true;
  1649. end
  1650. else
  1651. vs:=nil;
  1652. consume(_ID);
  1653. if assigned(vs) and
  1654. (
  1655. not had_generic or
  1656. not (token in [_PROCEDURE,_FUNCTION,_CLASS])
  1657. ) then
  1658. begin
  1659. vs.register_sym;
  1660. sc.add(vs);
  1661. recst.insertsym(vs);
  1662. had_generic:=false;
  1663. end
  1664. else
  1665. vs.free;
  1666. until not try_to_consume(_COMMA);
  1667. if m_delphi in current_settings.modeswitches then
  1668. block_type:=bt_var_type
  1669. else
  1670. block_type:=old_block_type;
  1671. if had_generic and (sc.count=0) then
  1672. break;
  1673. consume(_COLON);
  1674. if attr_element_count=0 then
  1675. attr_element_count:=sc.Count;
  1676. typepos:=current_filepos;
  1677. { make sure that the correct genericdef is set up, especially if
  1678. we're dealing with anonymous type declarations }
  1679. gendef:=nil;
  1680. if df_specialization in current_structdef.defoptions then
  1681. begin
  1682. srsymtable:=current_structdef.genericdef.getsymtable(gs_record);
  1683. if not assigned(srsymtable) then
  1684. internalerror(2024041204);
  1685. srsym:=tsym(srsymtable.find(tabstractvarsym(sc[0]).name));
  1686. if not assigned(srsym) then
  1687. internalerror(2024041205);
  1688. if srsym.typ<>fieldvarsym then
  1689. internalerror(2024041206);
  1690. gendef:=tfieldvarsym(srsym).vardef;
  1691. end;
  1692. read_anon_type(hdef,false,tstoreddef(gendef));
  1693. maybe_guarantee_record_typesym(hdef,symtablestack.top);
  1694. {$ifdef wasm}
  1695. if is_wasm_reference_type(hdef) then
  1696. messagepos(typepos,sym_e_wasm_ref_types_cannot_be_used_in_records);
  1697. {$endif wasm}
  1698. block_type:=bt_var;
  1699. { allow only static fields reference to struct where they are declared }
  1700. if not (vd_class in options) then
  1701. begin
  1702. if not check_allowed_for_var_or_const(hdef,true) then
  1703. { for error recovery or compiler will crash later }
  1704. hdef:=generrordef;
  1705. end;
  1706. { field type is a generic param so set a flag in the struct }
  1707. if assigned(hdef.typesym) and (sp_generic_para in hdef.typesym.symoptions) then
  1708. include(current_structdef.defoptions,df_has_generic_fields);
  1709. { Process procvar directives }
  1710. if maybe_parse_proc_directives(hdef) then
  1711. semicoloneaten:=true;
  1712. {$if defined(powerpc) or defined(powerpc64)}
  1713. { from gcc/gcc/config/rs6000/rs6000.h:
  1714. /* APPLE LOCAL begin Macintosh alignment 2002-1-22 ff */
  1715. /* Return the alignment of a struct based on the Macintosh PowerPC
  1716. alignment rules. In general the alignment of a struct is
  1717. determined by the greatest alignment of its elements. However, the
  1718. PowerPC rules cause the alignment of a struct to peg at word
  1719. alignment except when the first field has greater than word
  1720. (32-bit) alignment, in which case the alignment is determined by
  1721. the alignment of the first field. */
  1722. }
  1723. { TODO: check whether this is also for AIX }
  1724. if (target_info.abi in [abi_powerpc_aix,abi_powerpc_darwin]) and
  1725. is_first_type and
  1726. (symtablestack.top.symtabletype=recordsymtable) and
  1727. (trecordsymtable(symtablestack.top).usefieldalignment=C_alignment) then
  1728. begin
  1729. tempdef:=hdef;
  1730. while tempdef.typ=arraydef do
  1731. tempdef:=tarraydef(tempdef).elementdef;
  1732. if tempdef.typ<>recorddef then
  1733. maxpadalign:=tempdef.alignment
  1734. else
  1735. maxpadalign:=trecorddef(tempdef).padalignment;
  1736. if (maxpadalign>4) and
  1737. (maxpadalign>trecordsymtable(symtablestack.top).padalignment) then
  1738. trecordsymtable(symtablestack.top).padalignment:=maxpadalign;
  1739. is_first_type:=false;
  1740. end;
  1741. {$endif powerpc or powerpc64}
  1742. { types that use init/final are not allowed in variant parts, but
  1743. classes are allowed }
  1744. if (variantrecordlevel>0) then
  1745. if is_managed_type(hdef) then
  1746. Message(parser_e_cant_use_inittable_here);
  1747. { try to parse the hint directives }
  1748. hintsymoptions:=[];
  1749. deprecatedmsg:=nil;
  1750. try_consume_hintdirective(hintsymoptions,deprecatedmsg);
  1751. { update variable type and hints }
  1752. for i:=0 to sc.count-1 do
  1753. begin
  1754. fieldvs:=tfieldvarsym(sc[i]);
  1755. fieldvs.vardef:=hdef;
  1756. { insert any additional hint directives }
  1757. fieldvs.symoptions := fieldvs.symoptions + hintsymoptions;
  1758. if deprecatedmsg<>nil then
  1759. fieldvs.deprecatedmsg:=stringdup(deprecatedmsg^);
  1760. end;
  1761. stringdispose(deprecatedmsg);
  1762. { Records and objects can't have default values }
  1763. { for a record there doesn't need to be a ; before the END or ) }
  1764. if not(token in [_END,_RKLAMMER]) and
  1765. not(semicoloneaten) then
  1766. consume(_SEMICOLON);
  1767. { Parse procvar directives after ; }
  1768. maybe_parse_proc_directives(hdef);
  1769. { Add calling convention for procvar }
  1770. if (
  1771. (hdef.typ=procvardef) or
  1772. is_funcref(hdef)
  1773. ) and (hdef.typesym=nil) then
  1774. begin
  1775. if (hdef.typ=procvardef) and (po_is_function_ref in tprocvardef(hdef).procoptions) then
  1776. begin
  1777. if not (m_function_references in current_settings.modeswitches) and
  1778. not (po_is_block in tprocvardef(hdef).procoptions) then
  1779. messagepos(typepos,sym_e_error_in_type_def)
  1780. else
  1781. begin
  1782. if adjust_funcref(hdef,nil,nil) then
  1783. { the def was changed, so update it }
  1784. for i:=0 to sc.count-1 do
  1785. begin
  1786. fieldvs:=tfieldvarsym(sc[i]);
  1787. fieldvs.vardef:=hdef;
  1788. end;
  1789. if current_scanner.replay_stack_depth=0 then
  1790. hdef.register_def;
  1791. end;
  1792. end;
  1793. handle_calling_convention(hdef,hcc_default_actions_intf);
  1794. end;
  1795. if (vd_object in options) then
  1796. begin
  1797. { if it is not a class var section and token=STATIC then it is a class field too }
  1798. if not (vd_class in options) and try_to_consume(_STATIC) then
  1799. begin
  1800. consume(_SEMICOLON);
  1801. include(options,vd_class);
  1802. removeclassoption:=true;
  1803. end;
  1804. { Fields in Java classes/interfaces can have a separately
  1805. specified external name }
  1806. if is_java_class_or_interface(tdef(recst.defowner)) and
  1807. (oo_is_external in tobjectdef(recst.defowner).objectoptions) then
  1808. try_read_field_external_sc(sc);
  1809. end;
  1810. if (visibility=vis_published) and
  1811. not(is_class(hdef)) then
  1812. begin
  1813. MessagePos(tfieldvarsym(sc[0]).fileinfo,parser_e_cant_publish_that);
  1814. visibility:=vis_public;
  1815. end;
  1816. if (visibility=vis_published) and
  1817. not(oo_can_have_published in tobjectdef(hdef).objectoptions) and
  1818. not(m_delphi in current_settings.modeswitches) then
  1819. begin
  1820. MessagePos(tfieldvarsym(sc[0]).fileinfo,parser_e_only_publishable_classes_can_be_published);
  1821. visibility:=vis_public;
  1822. end;
  1823. if vd_class in options then
  1824. begin
  1825. { add static flag and staticvarsyms }
  1826. for i:=0 to sc.count-1 do
  1827. begin
  1828. fieldvs:=tfieldvarsym(sc[i]);
  1829. fieldvs.visibility:=visibility;
  1830. hstaticvs:=make_field_static(recst,fieldvs);
  1831. if vd_threadvar in options then
  1832. include(hstaticvs.varoptions,vo_is_thread_var);
  1833. if not parse_generic then
  1834. cnodeutils.insertbssdata(hstaticvs);
  1835. if vd_final in options then
  1836. hstaticvs.varspez:=vs_final;
  1837. end;
  1838. if removeclassoption then
  1839. begin
  1840. exclude(options,vd_class);
  1841. removeclassoption:=false;
  1842. end;
  1843. end;
  1844. if vd_final in options then
  1845. begin
  1846. { add final flag }
  1847. for i:=0 to sc.count-1 do
  1848. begin
  1849. fieldvs:=tfieldvarsym(sc[i]);
  1850. fieldvs.varspez:=vs_final;
  1851. end;
  1852. end;
  1853. if not(vd_canreorder in options) then
  1854. { add field(s) to the recordsymtable }
  1855. recst.addfieldlist(sc,false)
  1856. else
  1857. { we may reorder the fields before adding them to the symbol
  1858. table }
  1859. reorderlist.concatlistcopy(sc)
  1860. end;
  1861. if m_delphi in current_settings.modeswitches then
  1862. block_type:=bt_var_type
  1863. else
  1864. block_type:=old_block_type;
  1865. { Check for Case }
  1866. if (vd_record in options) and
  1867. try_to_consume(_CASE) then
  1868. begin
  1869. maxsize:=0;
  1870. maxalignment:=0;
  1871. maxpadalign:=0;
  1872. { already inside a variant record? if not, setup a new variantdesc chain }
  1873. if not(assigned(variantdesc)) then
  1874. variantdesc:=@trecorddef(trecordsymtable(recst).defowner).variantrecdesc;
  1875. { else just concat the info to the given one }
  1876. new(variantdesc^);
  1877. fillchar(variantdesc^^,sizeof(tvariantrecdesc),0);
  1878. { including a field declaration? }
  1879. fieldvs:=nil;
  1880. if token=_ID then
  1881. begin
  1882. sorg:=orgpattern;
  1883. hs:=pattern;
  1884. searchsym(hs,srsym,srsymtable);
  1885. if not(assigned(srsym) and (srsym.typ in [typesym,unitsym])) then
  1886. begin
  1887. consume(_ID);
  1888. consume(_COLON);
  1889. fieldvs:=cfieldvarsym.create(sorg,vs_value,generrordef,[]);
  1890. variantdesc^^.variantselector:=fieldvs;
  1891. symtablestack.top.insertsym(fieldvs);
  1892. end;
  1893. end;
  1894. read_anon_type(casetype,true,nil);
  1895. block_type:=bt_var;
  1896. if assigned(fieldvs) then
  1897. begin
  1898. fieldvs.vardef:=casetype;
  1899. recst.addfield(fieldvs,recst.currentvisibility);
  1900. end;
  1901. if not(is_ordinal(casetype))
  1902. {$ifndef cpu64bitaddr}
  1903. or is_64bitint(casetype)
  1904. {$endif cpu64bitaddr}
  1905. then
  1906. Message(type_e_ordinal_expr_expected);
  1907. consume(_OF);
  1908. UnionSymtable:=trecordsymtable.create('',current_settings.packrecords,current_settings.alignment.recordalignmin);
  1909. UnionDef:=crecorddef.create('',unionsymtable);
  1910. uniondef.isunion:=true;
  1911. startvarrecsize:=UnionSymtable.datasize;
  1912. { align the bitpacking to the next byte }
  1913. UnionSymtable.datasize:=startvarrecsize;
  1914. startvarrecalign:=UnionSymtable.fieldalignment;
  1915. startpadalign:=Unionsymtable.padalignment;
  1916. symtablestack.push(UnionSymtable);
  1917. repeat
  1918. SetLength(variantdesc^^.branches,length(variantdesc^^.branches)+1);
  1919. fillchar(variantdesc^^.branches[high(variantdesc^^.branches)],
  1920. sizeof(variantdesc^^.branches[high(variantdesc^^.branches)]),0);
  1921. repeat
  1922. pt:=comp_expr([ef_accept_equal]);
  1923. if not(pt.nodetype=ordconstn) then
  1924. Message(parser_e_illegal_expression);
  1925. inserttypeconv(pt,casetype);
  1926. { iso pascal does not support ranges in variant record definitions }
  1927. if (([m_iso,m_extpas]*current_settings.modeswitches)=[]) and try_to_consume(_POINTPOINT) then
  1928. pt:=crangenode.create(pt,comp_expr([ef_accept_equal]))
  1929. else
  1930. begin
  1931. with variantdesc^^.branches[high(variantdesc^^.branches)] do
  1932. begin
  1933. SetLength(values,length(values)+1);
  1934. values[high(values)]:=tordconstnode(pt).value;
  1935. end;
  1936. end;
  1937. pt.free;
  1938. if token=_COMMA then
  1939. consume(_COMMA)
  1940. else
  1941. break;
  1942. until false;
  1943. if m_delphi in current_settings.modeswitches then
  1944. block_type:=bt_var_type
  1945. else
  1946. block_type:=old_block_type;
  1947. consume(_COLON);
  1948. { read the vars }
  1949. consume(_LKLAMMER);
  1950. inc(variantrecordlevel);
  1951. if token<>_RKLAMMER then
  1952. read_record_fields([vd_record],nil,@variantdesc^^.branches[high(variantdesc^^.branches)].nestedvariant,hadgendummy,dummyattrelementcount);
  1953. dec(variantrecordlevel);
  1954. consume(_RKLAMMER);
  1955. { calculates maximal variant size }
  1956. maxsize:=max(maxsize,unionsymtable.datasize);
  1957. maxalignment:=max(maxalignment,unionsymtable.fieldalignment);
  1958. maxpadalign:=max(maxpadalign,unionsymtable.padalignment);
  1959. { the items of the next variant are overlayed }
  1960. unionsymtable.datasize:=startvarrecsize;
  1961. unionsymtable.fieldalignment:=startvarrecalign;
  1962. unionsymtable.padalignment:=startpadalign;
  1963. if (token<>_END) and (token<>_RKLAMMER) then
  1964. consume(_SEMICOLON)
  1965. else
  1966. break;
  1967. until (token=_END) or (token=_RKLAMMER);
  1968. symtablestack.pop(UnionSymtable);
  1969. { at last set the record size to that of the biggest variant }
  1970. unionsymtable.datasize:=maxsize;
  1971. unionsymtable.fieldalignment:=maxalignment;
  1972. unionsymtable.addalignmentpadding;
  1973. {$if defined(powerpc) or defined(powerpc64)}
  1974. { parent inherits the alignment padding if the variant is the first "field" of the parent record/variant }
  1975. if (target_info.system in [system_powerpc_darwin, system_powerpc_macosclassic, system_powerpc64_darwin]) and
  1976. is_first_type and
  1977. (recst.usefieldalignment=C_alignment) and
  1978. (maxpadalign>recst.padalignment) then
  1979. recst.padalignment:=maxpadalign;
  1980. {$endif powerpc or powerpc64}
  1981. { Align the offset where the union symtable is added }
  1982. case recst.usefieldalignment of
  1983. { allow the unionsymtable to be aligned however it wants }
  1984. { (within the global min/max limits) }
  1985. 0, { default }
  1986. C_alignment:
  1987. usedalign:=used_align(unionsymtable.recordalignment,current_settings.alignment.recordalignmin,current_settings.alignment.maxCrecordalign);
  1988. { 1 byte alignment if we are bitpacked }
  1989. bit_alignment:
  1990. usedalign:=1;
  1991. mac68k_alignment:
  1992. usedalign:=2;
  1993. { otherwise alignment at the packrecords alignment of the }
  1994. { current record }
  1995. else
  1996. usedalign:=used_align(recst.fieldalignment,current_settings.alignment.recordalignmin,current_settings.alignment.recordalignmax);
  1997. end;
  1998. offset:=align(recst.datasize,usedalign);
  1999. recst.datasize:=offset+unionsymtable.datasize;
  2000. if unionsymtable.recordalignment>recst.fieldalignment then
  2001. recst.fieldalignment:=unionsymtable.recordalignment;
  2002. trecordsymtable(recst).insertunionst(Unionsymtable,offset);
  2003. uniondef.owner.deletedef(uniondef);
  2004. end;
  2005. { free the list }
  2006. sc.free;
  2007. {$ifdef powerpc}
  2008. is_first_type := false;
  2009. {$endif powerpc}
  2010. block_type:=old_block_type;
  2011. end;
  2012. end.