pdecvar.pas 75 KB

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