pdecvar.pas 80 KB

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