pdecvar.pas 68 KB

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