pdecvar.pas 69 KB

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