pdecvar.pas 67 KB

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