pdecvar.pas 69 KB

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