pdecl.pas 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Does declaration (but not type) parsing for Free Pascal
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit pdecl;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. { common }
  22. cclasses,
  23. { global }
  24. globtype,
  25. { symtable }
  26. symsym,symdef,
  27. { pass_1 }
  28. node;
  29. function readconstant(const orgname:string;const filepos:tfileposinfo; out nodetype: tnodetype):tconstsym;
  30. procedure const_dec(out had_generic:boolean);
  31. procedure consts_dec(in_structure, allow_typed_const: boolean;out had_generic:boolean);
  32. procedure label_dec;
  33. procedure type_dec(out had_generic:boolean);
  34. procedure types_dec(in_structure: boolean;out had_generic:boolean;var rtti_attrs_def: trtti_attribute_list);
  35. procedure var_dec(out had_generic:boolean);
  36. procedure threadvar_dec(out had_generic:boolean);
  37. procedure property_dec;
  38. procedure resourcestring_dec(out had_generic:boolean);
  39. procedure parse_rttiattributes(var rtti_attrs_def:trtti_attribute_list);
  40. procedure add_synthetic_rtti_function_declarations(rtti_attrs_def:trtti_attribute_list;name:shortstring);
  41. implementation
  42. uses
  43. SysUtils,
  44. { common }
  45. cutils,
  46. { global }
  47. globals,tokens,verbose,widestr,constexp,
  48. systems,aasmdata,fmodule,compinnr,
  49. { symtable }
  50. symconst,symbase,symtype,symcpu,symcreat,defutil,defcmp,symtable,
  51. { pass 1 }
  52. ninl,ncon,nobj,ngenutil,nld,nmem,ncal,pass_1,
  53. { parser }
  54. scanner,
  55. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,pgenutil,pparautl,
  56. {$ifdef jvm}
  57. pjvm,
  58. {$endif}
  59. { cpu-information }
  60. cpuinfo
  61. ;
  62. var
  63. system_custom_attribute_def: tobjectdef = nil;
  64. function is_system_custom_attribute_descendant(def:tdef):boolean;
  65. begin
  66. if system_custom_attribute_def=nil then
  67. system_custom_attribute_def:=tobjectdef(search_system_type('TCUSTOMATTRIBUTE').typedef);
  68. Result:=def_is_related(def,system_custom_attribute_def);
  69. end;
  70. function readconstant(const orgname:string;const filepos:tfileposinfo; out nodetype: tnodetype):tconstsym;
  71. var
  72. hp : tconstsym;
  73. p : tnode;
  74. ps : pconstset;
  75. pd : pbestreal;
  76. pg : pguid;
  77. sp : pchar;
  78. pw : pcompilerwidestring;
  79. storetokenpos : tfileposinfo;
  80. begin
  81. readconstant:=nil;
  82. if orgname='' then
  83. internalerror(9584582);
  84. hp:=nil;
  85. p:=comp_expr([ef_accept_equal]);
  86. nodetype:=p.nodetype;
  87. storetokenpos:=current_tokenpos;
  88. current_tokenpos:=filepos;
  89. case p.nodetype of
  90. ordconstn:
  91. begin
  92. if p.resultdef.typ=pointerdef then
  93. hp:=cconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  94. else
  95. hp:=cconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  96. end;
  97. stringconstn:
  98. begin
  99. if is_wide_or_unicode_string(p.resultdef) then
  100. begin
  101. initwidestring(pw);
  102. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  103. hp:=cconstsym.create_wstring(orgname,constwstring,pw);
  104. end
  105. else
  106. begin
  107. getmem(sp,tstringconstnode(p).len+1);
  108. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  109. { if a non-default ansistring code page has been specified,
  110. keep it }
  111. if is_ansistring(p.resultdef) and
  112. (tstringdef(p.resultdef).encoding<>0) then
  113. hp:=cconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len,p.resultdef)
  114. else
  115. hp:=cconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len,nil);
  116. end;
  117. end;
  118. realconstn :
  119. begin
  120. new(pd);
  121. pd^:=trealconstnode(p).value_real;
  122. hp:=cconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  123. end;
  124. setconstn :
  125. begin
  126. new(ps);
  127. ps^:=tsetconstnode(p).value_set^;
  128. hp:=cconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  129. end;
  130. pointerconstn :
  131. begin
  132. hp:=cconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  133. end;
  134. niln :
  135. begin
  136. hp:=cconstsym.create_ord(orgname,constnil,0,p.resultdef);
  137. end;
  138. typen :
  139. begin
  140. if is_interface(p.resultdef) then
  141. begin
  142. if assigned(tobjectdef(p.resultdef).iidguid) then
  143. begin
  144. new(pg);
  145. pg^:=tobjectdef(p.resultdef).iidguid^;
  146. hp:=cconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  147. end
  148. else
  149. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  150. end
  151. else
  152. Message(parser_e_illegal_expression);
  153. end;
  154. inlinen:
  155. begin
  156. { this situation only happens if a intrinsic is parsed that has a
  157. generic type as its argument. As we don't know certain
  158. information about the final type yet, we need to use safe
  159. values (mostly 0, except for (Bit)SizeOf()) }
  160. if not parse_generic then
  161. Message(parser_e_illegal_expression);
  162. case tinlinenode(p).inlinenumber of
  163. in_sizeof_x:
  164. begin
  165. hp:=cconstsym.create_ord(orgname,constord,1,p.resultdef);
  166. end;
  167. in_bitsizeof_x:
  168. begin
  169. hp:=cconstsym.create_ord(orgname,constord,8,p.resultdef);
  170. end;
  171. { add other cases here if necessary }
  172. else
  173. Message(parser_e_illegal_expression);
  174. end;
  175. end;
  176. else
  177. Message(parser_e_illegal_expression);
  178. end;
  179. current_tokenpos:=storetokenpos;
  180. p.free;
  181. readconstant:=hp;
  182. end;
  183. procedure const_dec(out had_generic:boolean);
  184. begin
  185. consume(_CONST);
  186. consts_dec(false,true,had_generic);
  187. end;
  188. procedure consts_dec(in_structure, allow_typed_const: boolean;out had_generic:boolean);
  189. var
  190. orgname : TIDString;
  191. hdef : tdef;
  192. sym : tsym;
  193. dummysymoptions : tsymoptions;
  194. deprecatedmsg : pshortstring;
  195. storetokenpos,filepos : tfileposinfo;
  196. nodetype : tnodetype;
  197. old_block_type : tblock_type;
  198. first,
  199. isgeneric,
  200. skipequal : boolean;
  201. tclist : tasmlist;
  202. varspez : tvarspez;
  203. begin
  204. old_block_type:=block_type;
  205. block_type:=bt_const;
  206. had_generic:=false;
  207. first:=true;
  208. repeat
  209. orgname:=orgpattern;
  210. filepos:=current_tokenpos;
  211. isgeneric:=not (m_delphi in current_settings.modeswitches) and (token=_ID) and (idtoken=_GENERIC);
  212. consume(_ID);
  213. case token of
  214. _EQ:
  215. begin
  216. consume(_EQ);
  217. sym:=readconstant(orgname,filepos,nodetype);
  218. { Support hint directives }
  219. dummysymoptions:=[];
  220. deprecatedmsg:=nil;
  221. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  222. if assigned(sym) then
  223. begin
  224. sym.symoptions:=sym.symoptions+dummysymoptions;
  225. sym.deprecatedmsg:=deprecatedmsg;
  226. sym.visibility:=symtablestack.top.currentvisibility;
  227. symtablestack.top.insert(sym);
  228. {$ifdef jvm}
  229. { for the JVM target, some constants need to be
  230. initialized at run time (enums, sets) -> create fake
  231. typed const to do so (at least if they are visible
  232. outside this routine, since we won't directly access
  233. these symbols in the generated code) }
  234. if (symtablestack.top.symtablelevel<normal_function_level) and
  235. assigned(tconstsym(sym).constdef) and
  236. (tconstsym(sym).constdef.typ in [enumdef,setdef]) then
  237. jvm_add_typed_const_initializer(tconstsym(sym));
  238. {$endif}
  239. end
  240. else
  241. stringdispose(deprecatedmsg);
  242. consume(_SEMICOLON);
  243. end;
  244. _COLON:
  245. begin
  246. if not allow_typed_const then
  247. begin
  248. Message(parser_e_no_typed_const);
  249. consume_all_until(_SEMICOLON);
  250. end;
  251. { set the blocktype first so a consume also supports a
  252. caret, to support const s : ^string = nil }
  253. block_type:=bt_const_type;
  254. consume(_COLON);
  255. read_anon_type(hdef,false);
  256. block_type:=bt_const;
  257. skipequal:=false;
  258. { create symbol }
  259. storetokenpos:=current_tokenpos;
  260. current_tokenpos:=filepos;
  261. if not (cs_typed_const_writable in current_settings.localswitches) then
  262. varspez:=vs_const
  263. else
  264. varspez:=vs_value;
  265. { if we are dealing with structure const then we need to handle it as a
  266. structure static variable: create a symbol in unit symtable and a reference
  267. to it from the structure or linking will fail }
  268. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  269. begin
  270. { note: we keep hdef so that we might at least read the
  271. constant data correctly for error recovery }
  272. check_allowed_for_var_or_const(hdef,false);
  273. sym:=cfieldvarsym.create(orgname,varspez,hdef,[],true);
  274. symtablestack.top.insert(sym);
  275. sym:=make_field_static(symtablestack.top,tfieldvarsym(sym));
  276. end
  277. else
  278. begin
  279. sym:=cstaticvarsym.create(orgname,varspez,hdef,[],true);
  280. sym.visibility:=symtablestack.top.currentvisibility;
  281. symtablestack.top.insert(sym);
  282. end;
  283. current_tokenpos:=storetokenpos;
  284. { procvar can have proc directives, but not type references }
  285. if (hdef.typ=procvardef) and
  286. (hdef.typesym=nil) then
  287. begin
  288. { support p : procedure;stdcall=nil; }
  289. if try_to_consume(_SEMICOLON) then
  290. begin
  291. if check_proc_directive(true) then
  292. parse_var_proc_directives(sym)
  293. else
  294. begin
  295. Message(parser_e_proc_directive_expected);
  296. skipequal:=true;
  297. end;
  298. end
  299. else
  300. { support p : procedure stdcall=nil; }
  301. begin
  302. if check_proc_directive(true) then
  303. parse_var_proc_directives(sym);
  304. end;
  305. { add default calling convention }
  306. handle_calling_convention(tabstractprocdef(hdef),hcc_default_actions_intf);
  307. end;
  308. if not skipequal then
  309. begin
  310. { get init value }
  311. consume(_EQ);
  312. if (cs_typed_const_writable in current_settings.localswitches) then
  313. tclist:=current_asmdata.asmlists[al_typedconsts]
  314. else
  315. tclist:=current_asmdata.asmlists[al_rotypedconsts];
  316. read_typed_const(tclist,tstaticvarsym(sym),in_structure);
  317. end;
  318. end;
  319. else
  320. if not first and isgeneric and (token in [_PROCEDURE,_FUNCTION,_CLASS]) then
  321. begin
  322. had_generic:=true;
  323. break;
  324. end
  325. else
  326. { generate an error }
  327. consume(_EQ);
  328. end;
  329. first:=false;
  330. until (token<>_ID) or
  331. (in_structure and
  332. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  333. ((m_final_fields in current_settings.modeswitches) and
  334. (idtoken=_FINAL))));
  335. block_type:=old_block_type;
  336. end;
  337. procedure label_dec;
  338. var
  339. labelsym : tlabelsym;
  340. begin
  341. consume(_LABEL);
  342. if not(cs_support_goto in current_settings.moduleswitches) then
  343. Message(sym_e_goto_and_label_not_supported);
  344. repeat
  345. if not(token in [_ID,_INTCONST]) then
  346. consume(_ID)
  347. else
  348. begin
  349. if token=_ID then
  350. labelsym:=clabelsym.create(orgpattern)
  351. else
  352. labelsym:=clabelsym.create(pattern);
  353. symtablestack.top.insert(labelsym);
  354. if m_non_local_goto in current_settings.modeswitches then
  355. begin
  356. if symtablestack.top.symtabletype=localsymtable then
  357. begin
  358. labelsym.jumpbuf:=clocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[],true);
  359. symtablestack.top.insert(labelsym.jumpbuf);
  360. end
  361. else
  362. begin
  363. labelsym.jumpbuf:=cstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[],true);
  364. symtablestack.top.insert(labelsym.jumpbuf);
  365. cnodeutils.insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  366. end;
  367. include(labelsym.jumpbuf.symoptions,sp_internal);
  368. { the buffer will be setup later, but avoid a hint }
  369. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  370. end;
  371. consume(token);
  372. end;
  373. if token<>_SEMICOLON then consume(_COMMA);
  374. until not(token in [_ID,_INTCONST]);
  375. consume(_SEMICOLON);
  376. end;
  377. function find_create_constructor(objdef:tobjectdef):tsymentry;
  378. begin
  379. while assigned(objdef) do
  380. begin
  381. result:=objdef.symtable.Find('CREATE');
  382. if assigned(result) then
  383. exit;
  384. objdef:=objdef.childof;
  385. end;
  386. // A class without a constructor called 'create'?!?
  387. internalerror(2012111101);
  388. end;
  389. procedure parse_rttiattributes(var rtti_attrs_def:trtti_attribute_list);
  390. function read_attr_paras:tnode;
  391. var
  392. old_block_type : tblock_type;
  393. begin
  394. if try_to_consume(_LKLAMMER) then
  395. begin
  396. { we only want constants here }
  397. old_block_type:=block_type;
  398. block_type:=bt_const;
  399. result:=parse_paras(false,false,_RKLAMMER);
  400. block_type:=old_block_type;
  401. consume(_RKLAMMER);
  402. end
  403. else
  404. result:=nil;
  405. end;
  406. var
  407. p,paran,pcalln : tnode;
  408. od : tobjectdef;
  409. constrsym : tsymentry;
  410. typesym : ttypesym;
  411. begin
  412. consume(_LECKKLAMMER);
  413. { Parse attribute type }
  414. p:=factor(false,[ef_type_only,ef_check_attr_suffix]);
  415. if p.nodetype=typen then
  416. begin
  417. typesym:=ttypesym(ttypenode(p).typesym);
  418. od:=tobjectdef(ttypenode(p).typedef);
  419. { Check if the attribute class is related to TCustomAttribute }
  420. if not is_system_custom_attribute_descendant(od) then
  421. incompatibletypes(od,system_custom_attribute_def);
  422. paran:=read_attr_paras;
  423. { Search the tprocdef of the constructor which has to be called. }
  424. constrsym:=find_create_constructor(od);
  425. if constrsym.typ<>procsym then
  426. internalerror(2018102301);
  427. pcalln:=ccallnode.create(paran,tprocsym(constrsym),od.symtable,cloadvmtaddrnode.create(p),[],nil);
  428. p:=nil;
  429. typecheckpass(pcalln);
  430. if pcalln.nodetype<>errorn then
  431. begin
  432. { Add attribute to attribute list which will be added
  433. to the property which is defined next. }
  434. if not assigned(rtti_attrs_def) then
  435. rtti_attrs_def:=trtti_attribute_list.create;
  436. rtti_attrs_def.addattribute(typesym,pcalln);
  437. end;
  438. end
  439. else
  440. begin
  441. Message(type_e_type_id_expected);
  442. { try to recover by nevertheless reading the parameters (if any) }
  443. read_attr_paras.free;
  444. end;
  445. p.free;
  446. consume(_RECKKLAMMER);
  447. end;
  448. procedure add_synthetic_rtti_function_declarations(rtti_attrs_def:trtti_attribute_list;name:shortstring);
  449. var
  450. i : Integer;
  451. sstate : tscannerstate;
  452. attribute : trtti_attribute;
  453. pd : tprocdef;
  454. begin
  455. name:=StringReplace(name,'.','_',[rfReplaceAll]);
  456. for i:=0 to rtti_attrs_def.get_attribute_count-1 do
  457. begin
  458. attribute:=trtti_attribute(rtti_attrs_def.rtti_attributes[i]);
  459. replace_scanner('rtti_class_attributes',sstate);
  460. if str_parse_method_dec('function rtti_'+name+'_'+IntToStr(i)+':'+ attribute.typesym.Name +';',potype_function,false,tabstractrecorddef(ttypesym(attribute.typesym).typedef),pd) then
  461. pd.synthetickind:=tsk_get_rttiattribute
  462. else
  463. internalerror(2012052601);
  464. pd.skpara:=attribute;
  465. attribute.symbolname:=pd.mangledname;
  466. restore_scanner(sstate);
  467. end;
  468. end;
  469. procedure types_dec(in_structure: boolean;out had_generic:boolean;var rtti_attrs_def: trtti_attribute_list);
  470. function determine_generic_def(name:tidstring):tstoreddef;
  471. var
  472. hashedid : THashedIDString;
  473. pd : tprocdef;
  474. sym : tsym;
  475. begin
  476. result:=nil;
  477. { check whether this is a declaration of a type inside a
  478. specialization }
  479. if assigned(current_structdef) and
  480. (df_specialization in current_structdef.defoptions) then
  481. begin
  482. if not assigned(current_structdef.genericdef) or
  483. not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
  484. internalerror(2011052301);
  485. hashedid.id:=name;
  486. { we could be inside a method of the specialization
  487. instead of its declaration, so check that first (as
  488. local nested types aren't allowed we don't need to
  489. walk the symtablestack to find the localsymtable) }
  490. if symtablestack.top.symtabletype=localsymtable then
  491. begin
  492. { we are in a method }
  493. if not assigned(symtablestack.top.defowner) or
  494. (symtablestack.top.defowner.typ<>procdef) then
  495. internalerror(2011120701);
  496. pd:=tprocdef(symtablestack.top.defowner);
  497. if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
  498. internalerror(2011120702);
  499. sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
  500. end
  501. else
  502. sym:=nil;
  503. if not assigned(sym) or not (sym.typ=typesym) then
  504. begin
  505. { now search in the declaration of the generic }
  506. sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
  507. if not assigned(sym) or not (sym.typ=typesym) then
  508. internalerror(2011052302);
  509. end;
  510. { use the corresponding type in the generic's symtable as
  511. genericdef for the specialized type }
  512. result:=tstoreddef(ttypesym(sym).typedef);
  513. end;
  514. end;
  515. procedure finalize_class_external_status(od: tobjectdef);
  516. begin
  517. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  518. begin
  519. { formal definition: x = objcclass external; }
  520. exclude(od.objectoptions,oo_is_forward);
  521. include(od.objectoptions,oo_is_formal);
  522. end;
  523. end;
  524. var
  525. typename,orgtypename,
  526. gentypename,genorgtypename : TIDString;
  527. newtype : ttypesym;
  528. sym : tsym;
  529. hdef : tdef;
  530. defpos,storetokenpos : tfileposinfo;
  531. old_block_type : tblock_type;
  532. old_checkforwarddefs: TFPObjectList;
  533. objecttype : tobjecttyp;
  534. first,
  535. isgeneric,
  536. isunique,
  537. istyperenaming : boolean;
  538. generictypelist : tfphashobjectlist;
  539. generictokenbuf : tdynamicarray;
  540. vmtbuilder : TVMTBuilder;
  541. p:tnode;
  542. gendef : tstoreddef;
  543. s : shortstring;
  544. i : longint;
  545. {$ifdef x86}
  546. segment_register: string;
  547. {$endif x86}
  548. begin
  549. old_block_type:=block_type;
  550. { save unit container of forward declarations -
  551. we can be inside nested class type block }
  552. old_checkforwarddefs:=current_module.checkforwarddefs;
  553. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  554. block_type:=bt_type;
  555. hdef:=nil;
  556. first:=true;
  557. had_generic:=false;
  558. repeat
  559. defpos:=current_tokenpos;
  560. istyperenaming:=false;
  561. generictypelist:=nil;
  562. generictokenbuf:=nil;
  563. { class attribute definitions? }
  564. if m_prefixed_attributes in current_settings.modeswitches then
  565. while token=_LECKKLAMMER do
  566. parse_rttiattributes(rtti_attrs_def);
  567. { fpc generic declaration? }
  568. if first then
  569. had_generic:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  570. isgeneric:=had_generic;
  571. typename:=pattern;
  572. orgtypename:=orgpattern;
  573. consume(_ID);
  574. { delphi generic declaration? }
  575. if (m_delphi in current_settings.modeswitches) then
  576. isgeneric:=token=_LSHARPBRACKET;
  577. { Generic type declaration? }
  578. if isgeneric then
  579. begin
  580. if assigned(current_genericdef) then
  581. Message(parser_f_no_generic_inside_generic);
  582. consume(_LSHARPBRACKET);
  583. generictypelist:=parse_generic_parameters(true);
  584. consume(_RSHARPBRACKET);
  585. { we are not freeing the type parameters, so register them }
  586. for i:=0 to generictypelist.count-1 do
  587. begin
  588. ttypesym(generictypelist[i]).register_sym;
  589. tstoreddef(ttypesym(generictypelist[i]).typedef).register_def;
  590. end;
  591. str(generictypelist.Count,s);
  592. gentypename:=typename+'$'+s;
  593. genorgtypename:=orgtypename+'$'+s;
  594. end
  595. else
  596. begin
  597. gentypename:=typename;
  598. genorgtypename:=orgtypename;
  599. end;
  600. consume(_EQ);
  601. { support 'ttype=type word' syntax }
  602. isunique:=try_to_consume(_TYPE);
  603. { MacPas object model is more like Delphi's than like TP's, but }
  604. { uses the object keyword instead of class }
  605. if (m_mac in current_settings.modeswitches) and
  606. (token = _OBJECT) then
  607. token := _CLASS;
  608. { Start recording a generic template }
  609. if assigned(generictypelist) then
  610. begin
  611. generictokenbuf:=tdynamicarray.create(256);
  612. current_scanner.startrecordtokens(generictokenbuf);
  613. end;
  614. { is the type already defined? -- must be in the current symtable,
  615. not in a nested symtable or one higher up the stack -> don't
  616. use searchsym & frinds! }
  617. sym:=tsym(symtablestack.top.find(gentypename));
  618. newtype:=nil;
  619. { found a symbol with this name? }
  620. if assigned(sym) then
  621. begin
  622. if (sym.typ=typesym) and
  623. { this should not be a symbol that was created by a generic
  624. that was declared earlier }
  625. not (
  626. (ttypesym(sym).typedef.typ=undefineddef) and
  627. (sp_generic_dummy in sym.symoptions)
  628. ) then
  629. begin
  630. if ((token=_CLASS) or
  631. (token=_INTERFACE) or
  632. (token=_DISPINTERFACE) or
  633. (token=_OBJCCLASS) or
  634. (token=_OBJCPROTOCOL) or
  635. (token=_OBJCCATEGORY)) and
  636. (assigned(ttypesym(sym).typedef)) and
  637. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  638. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  639. begin
  640. case token of
  641. _CLASS :
  642. objecttype:=default_class_type;
  643. _INTERFACE :
  644. case current_settings.interfacetype of
  645. it_interfacecom:
  646. objecttype:=odt_interfacecom;
  647. it_interfacecorba:
  648. objecttype:=odt_interfacecorba;
  649. it_interfacejava:
  650. objecttype:=odt_interfacejava;
  651. end;
  652. _DISPINTERFACE :
  653. objecttype:=odt_dispinterface;
  654. _OBJCCLASS,
  655. _OBJCCATEGORY :
  656. objecttype:=odt_objcclass;
  657. _OBJCPROTOCOL :
  658. objecttype:=odt_objcprotocol;
  659. else
  660. internalerror(200811072);
  661. end;
  662. consume(token);
  663. { determine the generic def in case we are in a nested type
  664. of a specialization }
  665. gendef:=determine_generic_def(gentypename);
  666. { we can ignore the result, the definition is modified }
  667. object_dec(objecttype,genorgtypename,newtype,gendef,generictypelist,tobjectdef(ttypesym(sym).typedef),ht_none);
  668. newtype:=ttypesym(sym);
  669. hdef:=newtype.typedef;
  670. end
  671. else
  672. message1(parser_h_type_redef,genorgtypename);
  673. end;
  674. end;
  675. { no old type reused ? Then insert this new type }
  676. if not assigned(newtype) then
  677. begin
  678. { insert the new type first with an errordef, so that
  679. referencing the type before it's really set it
  680. will give an error (PFV) }
  681. hdef:=generrordef;
  682. gendef:=nil;
  683. storetokenpos:=current_tokenpos;
  684. if isgeneric then
  685. begin
  686. { for generics we need to check whether a non-generic type
  687. already exists and if not we need to insert a symbol with
  688. the non-generic name (available in (org)typename) that is a
  689. undefineddef, so that inline specializations can be used }
  690. sym:=tsym(symtablestack.top.Find(typename));
  691. if not assigned(sym) then
  692. begin
  693. sym:=ctypesym.create(orgtypename,cundefineddef.create(true),true);
  694. Include(sym.symoptions,sp_generic_dummy);
  695. ttypesym(sym).typedef.typesym:=sym;
  696. sym.visibility:=symtablestack.top.currentvisibility;
  697. symtablestack.top.insert(sym);
  698. ttypesym(sym).typedef.owner:=sym.owner;
  699. end
  700. else
  701. { this is not allowed in non-Delphi modes }
  702. if not (m_delphi in current_settings.modeswitches) then
  703. Message1(sym_e_duplicate_id,genorgtypename)
  704. else
  705. begin
  706. { we need to find this symbol even if it's a variable or
  707. something else when doing an inline specialization }
  708. Include(sym.symoptions,sp_generic_dummy);
  709. add_generic_dummysym(sym);
  710. end;
  711. end
  712. else
  713. begin
  714. if assigned(sym) and (sym.typ=typesym) and
  715. (ttypesym(sym).typedef.typ=undefineddef) and
  716. (sp_generic_dummy in sym.symoptions) then
  717. begin
  718. { this is a symbol that was added by an earlier generic
  719. declaration, reuse it }
  720. newtype:=ttypesym(sym);
  721. newtype.typedef:=hdef;
  722. { use the correct casing }
  723. newtype.RealName:=genorgtypename;
  724. sym:=nil;
  725. end;
  726. { determine the generic def in case we are in a nested type
  727. of a specialization }
  728. gendef:=determine_generic_def(gentypename);
  729. end;
  730. { insert a new type if we don't reuse an existing symbol }
  731. if not assigned(newtype) then
  732. begin
  733. newtype:=ctypesym.create(genorgtypename,hdef,true);
  734. newtype.visibility:=symtablestack.top.currentvisibility;
  735. symtablestack.top.insert(newtype);
  736. end;
  737. current_tokenpos:=defpos;
  738. current_tokenpos:=storetokenpos;
  739. { read the type definition }
  740. read_named_type(hdef,newtype,gendef,generictypelist,false,isunique);
  741. { update the definition of the type }
  742. if assigned(hdef) then
  743. begin
  744. if df_generic in hdef.defoptions then
  745. { flag parent symtables that they now contain a generic }
  746. hdef.owner.includeoption(sto_has_generic);
  747. if assigned(hdef.typesym) then
  748. begin
  749. istyperenaming:=true;
  750. include(newtype.symoptions,sp_explicitrename);
  751. end;
  752. if isunique then
  753. begin
  754. if is_objc_class_or_protocol(hdef) or
  755. is_java_class_or_interface(hdef) then
  756. Message(parser_e_unique_unsupported);
  757. if is_object(hdef) or
  758. is_class_or_interface_or_dispinterface(hdef) then
  759. begin
  760. { just create a child class type; this is
  761. Delphi-compatible }
  762. hdef:=cobjectdef.create(tobjectdef(hdef).objecttype,genorgtypename,tobjectdef(hdef),true);
  763. end
  764. else
  765. begin
  766. hdef:=tstoreddef(hdef).getcopy;
  767. { check if it is an ansistirng(codepage) declaration }
  768. if is_ansistring(hdef) and try_to_consume(_LKLAMMER) then
  769. begin
  770. p:=comp_expr([ef_accept_equal]);
  771. consume(_RKLAMMER);
  772. if not is_constintnode(p) then
  773. begin
  774. Message(parser_e_illegal_expression);
  775. { error recovery }
  776. end
  777. else
  778. begin
  779. if (tordconstnode(p).value<0) or (tordconstnode(p).value>65535) then
  780. begin
  781. Message(parser_e_invalid_codepage);
  782. tordconstnode(p).value:=0;
  783. end;
  784. tstringdef(hdef).encoding:=int64(tordconstnode(p).value);
  785. end;
  786. p.free;
  787. end;
  788. if (hdef.typ in [pointerdef,classrefdef]) and
  789. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  790. current_module.checkforwarddefs.add(hdef);
  791. end;
  792. include(hdef.defoptions,df_unique);
  793. end;
  794. if not assigned(hdef.typesym) then
  795. begin
  796. hdef.typesym:=newtype;
  797. if sp_generic_dummy in newtype.symoptions then
  798. add_generic_dummysym(newtype);
  799. end;
  800. end;
  801. { in non-Delphi modes we need a reference to the generic def
  802. without the generic suffix, so it can be found easily when
  803. parsing method implementations }
  804. if isgeneric and assigned(sym) and
  805. not (m_delphi in current_settings.modeswitches) and
  806. (ttypesym(sym).typedef.typ=undefineddef) then
  807. { don't free the undefineddef as the defids rely on the count
  808. of the defs in the def list of the module}
  809. ttypesym(sym).typedef:=hdef;
  810. newtype.typedef:=hdef;
  811. { ensure that the type is registered when no specialization is
  812. currently done }
  813. if current_scanner.replay_stack_depth=0 then
  814. hdef.register_def;
  815. { KAZ: handle TGUID declaration in system unit }
  816. if (cs_compilesystem in current_settings.moduleswitches) and
  817. assigned(hdef) and
  818. (hdef.typ=recorddef) then
  819. begin
  820. if not assigned(rec_tguid) and
  821. (gentypename='TGUID') and
  822. (hdef.size=16) then
  823. rec_tguid:=trecorddef(hdef)
  824. else if not assigned(rec_jmp_buf) and
  825. (gentypename='JMP_BUF') then
  826. rec_jmp_buf:=trecorddef(hdef)
  827. else if not assigned(rec_exceptaddr) and
  828. (gentypename='TEXCEPTADDR') then
  829. rec_exceptaddr:=trecorddef(hdef);
  830. end;
  831. end;
  832. if assigned(hdef) then
  833. begin
  834. case hdef.typ of
  835. pointerdef :
  836. begin
  837. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  838. consume(_SEMICOLON);
  839. {$ifdef x86}
  840. {$ifdef i8086}
  841. if try_to_consume(_HUGE) then
  842. begin
  843. tcpupointerdef(hdef).x86pointertyp:=x86pt_huge;
  844. consume(_SEMICOLON);
  845. end
  846. else
  847. {$endif i8086}
  848. if try_to_consume(_FAR) then
  849. begin
  850. {$if defined(i8086)}
  851. tcpupointerdef(hdef).x86pointertyp:=x86pt_far;
  852. {$elseif defined(i386)}
  853. tcpupointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  854. {$elseif defined(x86_64)}
  855. { for compatibility with previous versions of fpc,
  856. far pointer = regular pointer on x86_64 }
  857. Message1(parser_w_ptr_type_ignored,'FAR');
  858. {$endif}
  859. consume(_SEMICOLON);
  860. end
  861. else
  862. if try_to_consume(_NEAR) then
  863. begin
  864. if token <> _SEMICOLON then
  865. begin
  866. segment_register:=get_stringconst;
  867. case UpCase(segment_register) of
  868. 'CS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_cs;
  869. 'DS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_ds;
  870. 'SS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_ss;
  871. 'ES': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_es;
  872. 'FS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  873. 'GS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_gs;
  874. else
  875. Message(asmr_e_invalid_register);
  876. end;
  877. end
  878. else
  879. tcpupointerdef(hdef).x86pointertyp:=x86pt_near;
  880. consume(_SEMICOLON);
  881. end;
  882. {$else x86}
  883. { Previous versions of FPC support declaring a pointer as
  884. far even on non-x86 platforms. }
  885. if try_to_consume(_FAR) then
  886. begin
  887. Message1(parser_w_ptr_type_ignored,'FAR');
  888. consume(_SEMICOLON);
  889. end;
  890. {$endif x86}
  891. end;
  892. procvardef :
  893. begin
  894. { in case of type renaming, don't parse proc directives }
  895. if istyperenaming then
  896. begin
  897. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  898. consume(_SEMICOLON);
  899. end
  900. else
  901. begin
  902. if not check_proc_directive(true) then
  903. begin
  904. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  905. consume(_SEMICOLON);
  906. end;
  907. parse_var_proc_directives(tsym(newtype));
  908. if po_is_function_ref in tprocvardef(hdef).procoptions then
  909. begin
  910. { these always support everything, no "of object" or
  911. "is_nested" is allowed }
  912. if is_nested_pd(tprocvardef(hdef)) or
  913. is_methodpointer(hdef) then
  914. cgmessage(type_e_function_reference_kind)
  915. else
  916. begin
  917. if (po_hascallingconvention in tprocvardef(hdef).procoptions) and
  918. (tprocvardef(hdef).proccalloption in [pocall_cdecl,pocall_mwpascal]) then
  919. begin
  920. include(tprocvardef(hdef).procoptions,po_is_block);
  921. { can't check yet whether the parameter types
  922. are valid for a block, since some of them
  923. may still be forwarddefs }
  924. end
  925. else
  926. { a regular anonymous function type: not yet supported }
  927. { the }
  928. Comment(V_Error,'Function references are not yet supported, only C blocks (add "cdecl;" at the end)');
  929. end
  930. end;
  931. handle_calling_convention(tprocvardef(hdef),hcc_default_actions_intf);
  932. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  933. consume(_SEMICOLON);
  934. end;
  935. end;
  936. objectdef :
  937. begin
  938. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  939. consume(_SEMICOLON);
  940. { change a forward and external class declaration into
  941. formal external definition, so the compiler does not
  942. expect an real definition later }
  943. if is_objc_class_or_protocol(hdef) or
  944. is_java_class_or_interface(hdef) then
  945. finalize_class_external_status(tobjectdef(hdef));
  946. { Build VMT indexes, skip for type renaming and forward classes }
  947. if (hdef.typesym=newtype) and
  948. not(oo_is_forward in tobjectdef(hdef).objectoptions) then
  949. begin
  950. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  951. vmtbuilder.generate_vmt;
  952. vmtbuilder.free;
  953. end;
  954. { If there are attribute-properties available, bind them to
  955. this object }
  956. if assigned(rtti_attrs_def) then
  957. begin
  958. add_synthetic_rtti_function_declarations(rtti_attrs_def,hdef.typesym.Name);
  959. tobjectdef(hdef).rtti_attribute_list:=rtti_attrs_def;
  960. rtti_attrs_def := nil;
  961. end;
  962. { In case of an objcclass, verify that all methods have a message
  963. name set. We only check this now, because message names can be set
  964. during the protocol (interface) mapping. At the same time, set the
  965. mangled names (these depend on the "external" name of the class),
  966. and mark private fields of external classes as "used" (to avoid
  967. bogus notes about them being unused)
  968. }
  969. { watch out for crashes in case of errors }
  970. if is_objc_class_or_protocol(hdef) and
  971. (not is_objccategory(hdef) or
  972. assigned(tobjectdef(hdef).childof)) then
  973. tobjectdef(hdef).finish_objc_data;
  974. if is_cppclass(hdef) then
  975. tobjectdef(hdef).finish_cpp_data;
  976. end;
  977. recorddef :
  978. begin
  979. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  980. consume(_SEMICOLON);
  981. end;
  982. else
  983. begin
  984. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  985. consume(_SEMICOLON);
  986. end;
  987. end;
  988. end;
  989. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  990. or is_objectpascal_helper(hdef)) then
  991. message(parser_e_cant_create_generics_of_this_type);
  992. { Stop recording a generic template }
  993. if assigned(generictypelist) then
  994. begin
  995. current_scanner.stoprecordtokens;
  996. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  997. { Generic is never a type renaming }
  998. hdef.typesym:=newtype;
  999. generictypelist.free;
  1000. end;
  1001. if not (m_delphi in current_settings.modeswitches) and
  1002. (token=_ID) and (idtoken=_GENERIC) then
  1003. begin
  1004. had_generic:=true;
  1005. consume(_ID);
  1006. if token in [_PROCEDURE,_FUNCTION,_CLASS] then
  1007. break;
  1008. end
  1009. else
  1010. had_generic:=false;
  1011. first:=false;
  1012. if assigned(rtti_attrs_def) and (rtti_attrs_def.get_attribute_count>0) then
  1013. Message1(scan_e_unresolved_attribute,trtti_attribute(rtti_attrs_def.rtti_attributes[0]).typesym.prettyname);
  1014. until ((token<>_ID) and (token<>_LECKKLAMMER)) or
  1015. (in_structure and
  1016. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  1017. ((m_final_fields in current_settings.modeswitches) and
  1018. (idtoken=_FINAL))));
  1019. { resolve type block forward declarations and restore a unit
  1020. container for them }
  1021. resolve_forward_types;
  1022. current_module.checkforwarddefs.free;
  1023. current_module.checkforwarddefs:=old_checkforwarddefs;
  1024. block_type:=old_block_type;
  1025. end;
  1026. { reads a type declaration to the symbol table }
  1027. procedure type_dec(out had_generic:boolean);
  1028. var
  1029. rtti_attrs_def: trtti_attribute_list;
  1030. begin
  1031. consume(_TYPE);
  1032. rtti_attrs_def := nil;
  1033. types_dec(false,had_generic,rtti_attrs_def);
  1034. end;
  1035. procedure var_dec(out had_generic:boolean);
  1036. { parses variable declarations and inserts them in }
  1037. { the top symbol table of symtablestack }
  1038. begin
  1039. consume(_VAR);
  1040. read_var_decls([vd_check_generic],had_generic);
  1041. end;
  1042. procedure property_dec;
  1043. { parses a global property (fpc mode feature) }
  1044. var
  1045. old_block_type: tblock_type;
  1046. begin
  1047. consume(_PROPERTY);
  1048. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  1049. message(parser_e_property_only_sgr);
  1050. old_block_type:=block_type;
  1051. block_type:=bt_const;
  1052. repeat
  1053. read_property_dec(false, nil);
  1054. consume(_SEMICOLON);
  1055. until token<>_ID;
  1056. block_type:=old_block_type;
  1057. end;
  1058. procedure threadvar_dec(out had_generic:boolean);
  1059. { parses thread variable declarations and inserts them in }
  1060. { the top symbol table of symtablestack }
  1061. begin
  1062. consume(_THREADVAR);
  1063. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  1064. message(parser_e_threadvars_only_sg);
  1065. if f_threading in features then
  1066. read_var_decls([vd_threadvar,vd_check_generic],had_generic)
  1067. else
  1068. begin
  1069. Message1(parser_f_unsupported_feature,featurestr[f_threading]);
  1070. read_var_decls([vd_check_generic],had_generic);
  1071. end;
  1072. end;
  1073. procedure resourcestring_dec(out had_generic:boolean);
  1074. var
  1075. orgname : TIDString;
  1076. p : tnode;
  1077. dummysymoptions : tsymoptions;
  1078. deprecatedmsg : pshortstring;
  1079. storetokenpos,filepos : tfileposinfo;
  1080. old_block_type : tblock_type;
  1081. sp : pchar;
  1082. sym : tsym;
  1083. first,
  1084. isgeneric : boolean;
  1085. begin
  1086. if target_info.system in systems_managed_vm then
  1087. message(parser_e_feature_unsupported_for_vm);
  1088. consume(_RESOURCESTRING);
  1089. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  1090. message(parser_e_resourcestring_only_sg);
  1091. first:=true;
  1092. had_generic:=false;
  1093. old_block_type:=block_type;
  1094. block_type:=bt_const;
  1095. repeat
  1096. orgname:=orgpattern;
  1097. filepos:=current_tokenpos;
  1098. isgeneric:=not (m_delphi in current_settings.modeswitches) and (token=_ID) and (idtoken=_GENERIC);
  1099. consume(_ID);
  1100. case token of
  1101. _EQ:
  1102. begin
  1103. consume(_EQ);
  1104. p:=comp_expr([ef_accept_equal]);
  1105. storetokenpos:=current_tokenpos;
  1106. current_tokenpos:=filepos;
  1107. sym:=nil;
  1108. case p.nodetype of
  1109. ordconstn:
  1110. begin
  1111. if is_constcharnode(p) then
  1112. begin
  1113. getmem(sp,2);
  1114. sp[0]:=chr(tordconstnode(p).value.svalue);
  1115. sp[1]:=#0;
  1116. sym:=cconstsym.create_string(orgname,constresourcestring,sp,1,nil);
  1117. end
  1118. else
  1119. Message(parser_e_illegal_expression);
  1120. end;
  1121. stringconstn:
  1122. with Tstringconstnode(p) do
  1123. begin
  1124. { resourcestrings are currently always single byte }
  1125. if cst_type in [cst_widestring,cst_unicodestring] then
  1126. changestringtype(getansistringdef);
  1127. getmem(sp,len+1);
  1128. move(value_str^,sp^,len+1);
  1129. sym:=cconstsym.create_string(orgname,constresourcestring,sp,len,nil);
  1130. end;
  1131. else
  1132. Message(parser_e_illegal_expression);
  1133. end;
  1134. current_tokenpos:=storetokenpos;
  1135. { Support hint directives }
  1136. dummysymoptions:=[];
  1137. deprecatedmsg:=nil;
  1138. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  1139. if assigned(sym) then
  1140. begin
  1141. sym.symoptions:=sym.symoptions+dummysymoptions;
  1142. sym.deprecatedmsg:=deprecatedmsg;
  1143. symtablestack.top.insert(sym);
  1144. end
  1145. else
  1146. stringdispose(deprecatedmsg);
  1147. consume(_SEMICOLON);
  1148. p.free;
  1149. end;
  1150. else
  1151. if not first and isgeneric and
  1152. (token in [_PROCEDURE, _FUNCTION, _CLASS]) then
  1153. begin
  1154. had_generic:=true;
  1155. break;
  1156. end
  1157. else
  1158. consume(_EQ);
  1159. end;
  1160. first:=false;
  1161. until token<>_ID;
  1162. block_type:=old_block_type;
  1163. end;
  1164. end.