pdecvar.pas 73 KB

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