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