pdecvar.pas 84 KB

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