pdecvar.pas 83 KB

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