pdecvar.pas 80 KB

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