pdecvar.pas 68 KB

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