pdecvar.pas 61 KB

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