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