pdecvar.pas 82 KB

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