pdecvar.pas 79 KB

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