pdecvar.pas 80 KB

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