pdecl.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832
  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):tconstsym;
  30. procedure const_dec;
  31. procedure consts_dec(in_structure: boolean);
  32. procedure label_dec;
  33. procedure type_dec;
  34. procedure types_dec(in_structure: boolean);
  35. procedure var_dec;
  36. procedure threadvar_dec;
  37. procedure property_dec(is_classpropery: boolean);
  38. procedure resourcestring_dec;
  39. { generics support }
  40. function parse_generic_parameters:TFPObjectList;
  41. procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
  42. implementation
  43. uses
  44. SysUtils,
  45. { common }
  46. cutils,
  47. { global }
  48. globals,tokens,verbose,widestr,constexp,
  49. systems,
  50. { aasm }
  51. aasmbase,aasmtai,aasmdata,fmodule,
  52. { symtable }
  53. symconst,symbase,symtype,symtable,paramgr,defutil,
  54. { pass 1 }
  55. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,
  56. { codegen }
  57. ncgutil,
  58. { parser }
  59. scanner,
  60. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,
  61. { cpu-information }
  62. cpuinfo
  63. ;
  64. function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
  65. var
  66. hp : tconstsym;
  67. p : tnode;
  68. ps : pconstset;
  69. pd : pbestreal;
  70. pg : pguid;
  71. sp : pchar;
  72. pw : pcompilerwidestring;
  73. storetokenpos : tfileposinfo;
  74. begin
  75. readconstant:=nil;
  76. if orgname='' then
  77. internalerror(9584582);
  78. hp:=nil;
  79. p:=comp_expr(true,false);
  80. storetokenpos:=current_tokenpos;
  81. current_tokenpos:=filepos;
  82. case p.nodetype of
  83. ordconstn:
  84. begin
  85. if p.resultdef.typ=pointerdef then
  86. hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  87. else
  88. hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  89. end;
  90. stringconstn:
  91. begin
  92. if is_wide_or_unicode_string(p.resultdef) then
  93. begin
  94. initwidestring(pw);
  95. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  96. hp:=tconstsym.create_wstring(orgname,constwstring,pw);
  97. end
  98. else
  99. begin
  100. getmem(sp,tstringconstnode(p).len+1);
  101. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  102. hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
  103. end;
  104. end;
  105. realconstn :
  106. begin
  107. new(pd);
  108. pd^:=trealconstnode(p).value_real;
  109. hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  110. end;
  111. setconstn :
  112. begin
  113. new(ps);
  114. ps^:=tsetconstnode(p).value_set^;
  115. hp:=tconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  116. end;
  117. pointerconstn :
  118. begin
  119. hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  120. end;
  121. niln :
  122. begin
  123. hp:=tconstsym.create_ord(orgname,constnil,0,p.resultdef);
  124. end;
  125. typen :
  126. begin
  127. if is_interface(p.resultdef) then
  128. begin
  129. if assigned(tobjectdef(p.resultdef).iidguid) then
  130. begin
  131. new(pg);
  132. pg^:=tobjectdef(p.resultdef).iidguid^;
  133. hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  134. end
  135. else
  136. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  137. end
  138. else
  139. Message(parser_e_illegal_expression);
  140. end;
  141. else
  142. Message(parser_e_illegal_expression);
  143. end;
  144. current_tokenpos:=storetokenpos;
  145. p.free;
  146. readconstant:=hp;
  147. end;
  148. procedure const_dec;
  149. begin
  150. consume(_CONST);
  151. consts_dec(false);
  152. end;
  153. procedure consts_dec(in_structure: boolean);
  154. var
  155. orgname : TIDString;
  156. hdef : tdef;
  157. sym, tmp : tsym;
  158. dummysymoptions : tsymoptions;
  159. deprecatedmsg : pshortstring;
  160. storetokenpos,filepos : tfileposinfo;
  161. old_block_type : tblock_type;
  162. skipequal : boolean;
  163. tclist : tasmlist;
  164. varspez : tvarspez;
  165. static_name : string;
  166. sl : tpropaccesslist;
  167. begin
  168. old_block_type:=block_type;
  169. block_type:=bt_const;
  170. repeat
  171. orgname:=orgpattern;
  172. filepos:=current_tokenpos;
  173. consume(_ID);
  174. case token of
  175. _EQ:
  176. begin
  177. consume(_EQ);
  178. sym:=readconstant(orgname,filepos);
  179. { Support hint directives }
  180. dummysymoptions:=[];
  181. deprecatedmsg:=nil;
  182. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  183. if assigned(sym) then
  184. begin
  185. sym.symoptions:=sym.symoptions+dummysymoptions;
  186. sym.deprecatedmsg:=deprecatedmsg;
  187. sym.visibility:=symtablestack.top.currentvisibility;
  188. symtablestack.top.insert(sym);
  189. end
  190. else
  191. stringdispose(deprecatedmsg);
  192. consume(_SEMICOLON);
  193. end;
  194. _COLON:
  195. begin
  196. { set the blocktype first so a consume also supports a
  197. caret, to support const s : ^string = nil }
  198. block_type:=bt_const_type;
  199. consume(_COLON);
  200. read_anon_type(hdef,false);
  201. block_type:=bt_const;
  202. skipequal:=false;
  203. { create symbol }
  204. storetokenpos:=current_tokenpos;
  205. current_tokenpos:=filepos;
  206. if not (cs_typed_const_writable in current_settings.localswitches) then
  207. varspez:=vs_const
  208. else
  209. varspez:=vs_value;
  210. { if we are dealing with structure const then we need to handle it as a
  211. structure static variable: create a symbol in unit symtable and a reference
  212. to it from the structure or linking will fail }
  213. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  214. begin
  215. { generate the symbol which reserves the space }
  216. static_name:=lower(generate_nested_name(symtablestack.top,'_'))+'_'+orgname;
  217. sym:=tstaticvarsym.create('$_static_'+static_name,varspez,hdef,[]);
  218. include(sym.symoptions,sp_internal);
  219. tabstractrecordsymtable(symtablestack.top).get_unit_symtable.insert(sym);
  220. { generate the symbol for the access }
  221. sl:=tpropaccesslist.create;
  222. sl.addsym(sl_load,sym);
  223. tmp:=tabsolutevarsym.create_ref(orgname,hdef,sl);
  224. tmp.visibility:=symtablestack.top.currentvisibility;
  225. symtablestack.top.insert(tmp);
  226. end
  227. else
  228. begin
  229. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  230. sym.visibility:=symtablestack.top.currentvisibility;
  231. symtablestack.top.insert(sym);
  232. end;
  233. current_tokenpos:=storetokenpos;
  234. { procvar can have proc directives, but not type references }
  235. if (hdef.typ=procvardef) and
  236. (hdef.typesym=nil) then
  237. begin
  238. { support p : procedure;stdcall=nil; }
  239. if try_to_consume(_SEMICOLON) then
  240. begin
  241. if check_proc_directive(true) then
  242. parse_var_proc_directives(sym)
  243. else
  244. begin
  245. Message(parser_e_proc_directive_expected);
  246. skipequal:=true;
  247. end;
  248. end
  249. else
  250. { support p : procedure stdcall=nil; }
  251. begin
  252. if check_proc_directive(true) then
  253. parse_var_proc_directives(sym);
  254. end;
  255. { add default calling convention }
  256. handle_calling_convention(tabstractprocdef(hdef));
  257. end;
  258. if not skipequal then
  259. begin
  260. { get init value }
  261. consume(_EQ);
  262. if (cs_typed_const_writable in current_settings.localswitches) then
  263. tclist:=current_asmdata.asmlists[al_rotypedconsts]
  264. else
  265. tclist:=current_asmdata.asmlists[al_typedconsts];
  266. read_typed_const(tclist,tstaticvarsym(sym),in_structure);
  267. end;
  268. end;
  269. else
  270. { generate an error }
  271. consume(_EQ);
  272. end;
  273. until (token<>_ID)or(in_structure and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
  274. block_type:=old_block_type;
  275. end;
  276. procedure label_dec;
  277. var
  278. labelsym : tlabelsym;
  279. begin
  280. consume(_LABEL);
  281. if not(cs_support_goto in current_settings.moduleswitches) then
  282. Message(sym_e_goto_and_label_not_supported);
  283. repeat
  284. if not(token in [_ID,_INTCONST]) then
  285. consume(_ID)
  286. else
  287. begin
  288. if token=_ID then
  289. labelsym:=tlabelsym.create(orgpattern)
  290. else
  291. labelsym:=tlabelsym.create(pattern);
  292. symtablestack.top.insert(labelsym);
  293. if m_non_local_goto in current_settings.modeswitches then
  294. begin
  295. if symtablestack.top.symtabletype=localsymtable then
  296. begin
  297. labelsym.jumpbuf:=tlocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  298. symtablestack.top.insert(labelsym.jumpbuf);
  299. end
  300. else
  301. begin
  302. labelsym.jumpbuf:=tstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  303. symtablestack.top.insert(labelsym.jumpbuf);
  304. insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  305. end;
  306. include(labelsym.jumpbuf.symoptions,sp_internal);
  307. { the buffer will be setup later, but avoid a hint }
  308. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  309. end;
  310. consume(token);
  311. end;
  312. if token<>_SEMICOLON then consume(_COMMA);
  313. until not(token in [_ID,_INTCONST]);
  314. consume(_SEMICOLON);
  315. end;
  316. function parse_generic_parameters:TFPObjectList;
  317. var
  318. generictype : ttypesym;
  319. begin
  320. result:=TFPObjectList.Create(false);
  321. repeat
  322. if token=_ID then
  323. begin
  324. generictype:=ttypesym.create(orgpattern,cundefinedtype);
  325. include(generictype.symoptions,sp_generic_para);
  326. result.add(generictype);
  327. end;
  328. consume(_ID);
  329. until not try_to_consume(_COMMA) ;
  330. end;
  331. procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
  332. var
  333. i: longint;
  334. generictype: ttypesym;
  335. st: tsymtable;
  336. begin
  337. def.genericdef:=genericdef;
  338. if not assigned(genericlist) then
  339. exit;
  340. case def.typ of
  341. recorddef,objectdef: st:=tabstractrecorddef(def).symtable;
  342. arraydef: st:=tarraydef(def).symtable;
  343. procvardef,procdef: st:=tabstractprocdef(def).parast;
  344. else
  345. internalerror(201101020);
  346. end;
  347. for i:=0 to genericlist.count-1 do
  348. begin
  349. generictype:=ttypesym(genericlist[i]);
  350. if generictype.typedef.typ=undefineddef then
  351. include(def.defoptions,df_generic)
  352. else
  353. include(def.defoptions,df_specialization);
  354. st.insert(generictype);
  355. end;
  356. end;
  357. procedure types_dec(in_structure: boolean);
  358. procedure finalize_objc_class_or_protocol_external_status(od: tobjectdef);
  359. begin
  360. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  361. begin
  362. { formal definition: x = objcclass external; }
  363. exclude(od.objectoptions,oo_is_forward);
  364. include(od.objectoptions,oo_is_formal);
  365. end;
  366. end;
  367. var
  368. typename,orgtypename : TIDString;
  369. newtype : ttypesym;
  370. sym : tsym;
  371. hdef : tdef;
  372. defpos,storetokenpos : tfileposinfo;
  373. old_block_type : tblock_type;
  374. old_checkforwarddefs: TFPObjectList;
  375. objecttype : tobjecttyp;
  376. isgeneric,
  377. isunique,
  378. istyperenaming : boolean;
  379. generictypelist : TFPObjectList;
  380. generictokenbuf : tdynamicarray;
  381. vmtbuilder : TVMTBuilder;
  382. i : integer;
  383. begin
  384. old_block_type:=block_type;
  385. { save unit container of forward declarations -
  386. we can be inside nested class type block }
  387. old_checkforwarddefs:=current_module.checkforwarddefs;
  388. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  389. block_type:=bt_type;
  390. repeat
  391. defpos:=current_tokenpos;
  392. istyperenaming:=false;
  393. generictypelist:=nil;
  394. generictokenbuf:=nil;
  395. { fpc generic declaration? }
  396. isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  397. typename:=pattern;
  398. orgtypename:=orgpattern;
  399. consume(_ID);
  400. { delphi generic declaration? }
  401. if (m_delphi in current_settings.modeswitches) then
  402. isgeneric:=token=_LSHARPBRACKET;
  403. { Generic type declaration? }
  404. if isgeneric then
  405. begin
  406. if assigned(current_genericdef) then
  407. Message(parser_f_no_generic_inside_generic);
  408. consume(_LSHARPBRACKET);
  409. generictypelist:=parse_generic_parameters;
  410. consume(_RSHARPBRACKET);
  411. end;
  412. consume(_EQ);
  413. { support 'ttype=type word' syntax }
  414. isunique:=try_to_consume(_TYPE);
  415. { MacPas object model is more like Delphi's than like TP's, but }
  416. { uses the object keyword instead of class }
  417. if (m_mac in current_settings.modeswitches) and
  418. (token = _OBJECT) then
  419. token := _CLASS;
  420. { Start recording a generic template }
  421. if assigned(generictypelist) then
  422. begin
  423. generictokenbuf:=tdynamicarray.create(256);
  424. current_scanner.startrecordtokens(generictokenbuf);
  425. end;
  426. { is the type already defined? -- must be in the current symtable,
  427. not in a nested symtable or one higher up the stack -> don't
  428. use searchsym & frinds! }
  429. sym:=tsym(symtablestack.top.find(typename));
  430. newtype:=nil;
  431. { found a symbol with this name? }
  432. if assigned(sym) then
  433. begin
  434. if (sym.typ=typesym) then
  435. begin
  436. if isgeneric then
  437. begin
  438. { overloading types is only allowed in mode Delphi }
  439. if not (m_delphi in current_settings.modeswitches) then
  440. Message1(sym_e_duplicate_id,orgtypename);
  441. for i:=0 to ttypesym(sym).gendeflist.Count-1 do
  442. { TODO : check whether the count of one of the defs is
  443. the same as that of the current declaration and
  444. print an error if so }
  445. ;
  446. end
  447. else
  448. if ((token=_CLASS) or
  449. (token=_INTERFACE) or
  450. (token=_DISPINTERFACE) or
  451. (token=_OBJCCLASS) or
  452. (token=_OBJCPROTOCOL) or
  453. (token=_OBJCCATEGORY)) and
  454. (assigned(ttypesym(sym).typedef)) and
  455. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  456. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  457. begin
  458. case token of
  459. _CLASS :
  460. objecttype:=odt_class;
  461. _INTERFACE :
  462. if current_settings.interfacetype=it_interfacecom then
  463. objecttype:=odt_interfacecom
  464. else
  465. objecttype:=odt_interfacecorba;
  466. _DISPINTERFACE :
  467. objecttype:=odt_dispinterface;
  468. _OBJCCLASS,
  469. _OBJCCATEGORY :
  470. objecttype:=odt_objcclass;
  471. _OBJCPROTOCOL :
  472. objecttype:=odt_objcprotocol;
  473. else
  474. internalerror(200811072);
  475. end;
  476. consume(token);
  477. { we can ignore the result, the definition is modified }
  478. object_dec(objecttype,orgtypename,nil,nil,tobjectdef(ttypesym(sym).typedef),ht_none);
  479. newtype:=ttypesym(sym);
  480. hdef:=newtype.typedef;
  481. end
  482. else
  483. if not (m_delphi in current_settings.modeswitches) and
  484. (ttypesym(sym).typedef.typ=undefineddef) and
  485. (ttypesym(sym).gendeflist.Count>0) then
  486. message1(sym_e_duplicate_id,orgtypename)
  487. else
  488. message1(parser_h_type_redef,orgtypename);
  489. end;
  490. end;
  491. { no old type reused ? Then insert this new type }
  492. if not assigned(newtype) then
  493. begin
  494. { insert the new type first with an errordef, so that
  495. referencing the type before it's really set it
  496. will give an error (PFV) }
  497. hdef:=generrordef;
  498. storetokenpos:=current_tokenpos;
  499. if isgeneric then
  500. begin
  501. if assigned(sym) then
  502. newtype:=ttypesym(sym)
  503. else
  504. begin
  505. { add the symbol with a undefineddef, so typesym can point
  506. to this symbol }
  507. newtype:=ttypesym.create(orgtypename,tundefineddef.create);
  508. newtype.typedef.typesym:=newtype;
  509. newtype.visibility:=symtablestack.top.currentvisibility;
  510. symtablestack.top.insert(newtype);
  511. newtype.typedef.owner:=newtype.owner;
  512. end;
  513. end
  514. else
  515. if assigned(sym) then
  516. newtype:=ttypesym(sym)
  517. else
  518. begin
  519. newtype:=ttypesym.create(orgtypename,hdef);
  520. newtype.visibility:=symtablestack.top.currentvisibility;
  521. symtablestack.top.insert(newtype);
  522. end;
  523. current_tokenpos:=defpos;
  524. current_tokenpos:=storetokenpos;
  525. { read the type definition }
  526. read_named_type(hdef,orgtypename,nil,generictypelist,false);
  527. { update the definition of the type }
  528. if assigned(hdef) then
  529. begin
  530. if assigned(hdef.typesym) then
  531. istyperenaming:=true;
  532. if isunique then
  533. begin
  534. if is_objc_class_or_protocol(hdef) then
  535. Message(parser_e_no_objc_unique);
  536. hdef:=tstoreddef(hdef).getcopy;
  537. { fix name, it is used e.g. for tables }
  538. if is_class_or_interface_or_dispinterface(hdef) then
  539. with tobjectdef(hdef) do
  540. begin
  541. stringdispose(objname);
  542. stringdispose(objrealname);
  543. objrealname:=stringdup(orgtypename);
  544. objname:=stringdup(upper(orgtypename));
  545. end;
  546. include(hdef.defoptions,df_unique);
  547. if (hdef.typ in [pointerdef,classrefdef]) and
  548. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  549. current_module.checkforwarddefs.add(hdef);
  550. end;
  551. if not assigned(hdef.typesym) then
  552. hdef.typesym:=newtype;
  553. end;
  554. if isgeneric then begin
  555. newtype.Owner.includeoption(sto_has_generic);
  556. newtype.gendeflist.Add(hdef)
  557. end else
  558. newtype.typedef:=hdef;
  559. { KAZ: handle TGUID declaration in system unit }
  560. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  561. (typename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  562. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  563. rec_tguid:=trecorddef(hdef);
  564. end;
  565. if assigned(hdef) then
  566. begin
  567. case hdef.typ of
  568. pointerdef :
  569. begin
  570. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  571. consume(_SEMICOLON);
  572. if try_to_consume(_FAR) then
  573. begin
  574. tpointerdef(hdef).is_far:=true;
  575. consume(_SEMICOLON);
  576. end;
  577. end;
  578. procvardef :
  579. begin
  580. { in case of type renaming, don't parse proc directives }
  581. if istyperenaming then
  582. begin
  583. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  584. consume(_SEMICOLON);
  585. end
  586. else
  587. begin
  588. if not check_proc_directive(true) then
  589. begin
  590. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  591. consume(_SEMICOLON);
  592. end;
  593. parse_var_proc_directives(tsym(newtype));
  594. handle_calling_convention(tprocvardef(hdef));
  595. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  596. consume(_SEMICOLON);
  597. end;
  598. end;
  599. objectdef :
  600. begin
  601. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  602. consume(_SEMICOLON);
  603. { change a forward and external objcclass declaration into
  604. formal external definition, so the compiler does not
  605. expect an real definition later }
  606. if is_objc_class_or_protocol(hdef) then
  607. finalize_objc_class_or_protocol_external_status(tobjectdef(hdef));
  608. { Build VMT indexes, skip for type renaming and forward classes }
  609. if (hdef.typesym=newtype) and
  610. not(oo_is_forward in tobjectdef(hdef).objectoptions) and
  611. not(df_generic in hdef.defoptions) then
  612. begin
  613. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  614. vmtbuilder.generate_vmt;
  615. vmtbuilder.free;
  616. end;
  617. { In case of an objcclass, verify that all methods have a message
  618. name set. We only check this now, because message names can be set
  619. during the protocol (interface) mapping. At the same time, set the
  620. mangled names (these depend on the "external" name of the class),
  621. and mark private fields of external classes as "used" (to avoid
  622. bogus notes about them being unused)
  623. }
  624. { watch out for crashes in case of errors }
  625. if is_objc_class_or_protocol(hdef) and
  626. (not is_objccategory(hdef) or
  627. assigned(tobjectdef(hdef).childof)) then
  628. tobjectdef(hdef).finish_objc_data;
  629. if is_cppclass(hdef) then
  630. tobjectdef(hdef).finish_cpp_data;
  631. end;
  632. recorddef :
  633. begin
  634. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  635. consume(_SEMICOLON);
  636. end;
  637. else
  638. begin
  639. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  640. consume(_SEMICOLON);
  641. end;
  642. end;
  643. end;
  644. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  645. or is_objectpascal_helper(hdef)) then
  646. message(parser_e_cant_create_generics_of_this_type);
  647. { Stop recording a generic template }
  648. if assigned(generictypelist) then
  649. begin
  650. current_scanner.stoprecordtokens;
  651. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  652. { Generic is never a type renaming }
  653. hdef.typesym:=newtype;
  654. generictypelist.free;
  655. end;
  656. until (token<>_ID)or(in_structure and (idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]));
  657. { resolve type block forward declarations and restore a unit
  658. container for them }
  659. resolve_forward_types;
  660. current_module.checkforwarddefs.free;
  661. current_module.checkforwarddefs:=old_checkforwarddefs;
  662. block_type:=old_block_type;
  663. end;
  664. { reads a type declaration to the symbol table }
  665. procedure type_dec;
  666. begin
  667. consume(_TYPE);
  668. types_dec(false);
  669. end;
  670. procedure var_dec;
  671. { parses variable declarations and inserts them in }
  672. { the top symbol table of symtablestack }
  673. begin
  674. consume(_VAR);
  675. read_var_decls([]);
  676. end;
  677. procedure property_dec(is_classpropery: boolean);
  678. var
  679. old_block_type : tblock_type;
  680. begin
  681. consume(_PROPERTY);
  682. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  683. message(parser_e_resourcestring_only_sg);
  684. old_block_type:=block_type;
  685. block_type:=bt_const;
  686. repeat
  687. read_property_dec(is_classpropery, nil);
  688. consume(_SEMICOLON);
  689. until token<>_ID;
  690. block_type:=old_block_type;
  691. end;
  692. procedure threadvar_dec;
  693. { parses thread variable declarations and inserts them in }
  694. { the top symbol table of symtablestack }
  695. begin
  696. consume(_THREADVAR);
  697. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  698. message(parser_e_threadvars_only_sg);
  699. read_var_decls([vd_threadvar]);
  700. end;
  701. procedure resourcestring_dec;
  702. var
  703. orgname : TIDString;
  704. p : tnode;
  705. dummysymoptions : tsymoptions;
  706. deprecatedmsg : pshortstring;
  707. storetokenpos,filepos : tfileposinfo;
  708. old_block_type : tblock_type;
  709. sp : pchar;
  710. sym : tsym;
  711. begin
  712. consume(_RESOURCESTRING);
  713. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  714. message(parser_e_resourcestring_only_sg);
  715. old_block_type:=block_type;
  716. block_type:=bt_const;
  717. repeat
  718. orgname:=orgpattern;
  719. filepos:=current_tokenpos;
  720. consume(_ID);
  721. case token of
  722. _EQ:
  723. begin
  724. consume(_EQ);
  725. p:=comp_expr(true,false);
  726. storetokenpos:=current_tokenpos;
  727. current_tokenpos:=filepos;
  728. sym:=nil;
  729. case p.nodetype of
  730. ordconstn:
  731. begin
  732. if is_constcharnode(p) then
  733. begin
  734. getmem(sp,2);
  735. sp[0]:=chr(tordconstnode(p).value.svalue);
  736. sp[1]:=#0;
  737. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  738. end
  739. else
  740. Message(parser_e_illegal_expression);
  741. end;
  742. stringconstn:
  743. with Tstringconstnode(p) do
  744. begin
  745. getmem(sp,len+1);
  746. move(value_str^,sp^,len+1);
  747. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  748. end;
  749. else
  750. Message(parser_e_illegal_expression);
  751. end;
  752. current_tokenpos:=storetokenpos;
  753. { Support hint directives }
  754. dummysymoptions:=[];
  755. deprecatedmsg:=nil;
  756. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  757. if assigned(sym) then
  758. begin
  759. sym.symoptions:=sym.symoptions+dummysymoptions;
  760. sym.deprecatedmsg:=deprecatedmsg;
  761. symtablestack.top.insert(sym);
  762. end
  763. else
  764. stringdispose(deprecatedmsg);
  765. consume(_SEMICOLON);
  766. p.free;
  767. end;
  768. else consume(_EQ);
  769. end;
  770. until token<>_ID;
  771. block_type:=old_block_type;
  772. end;
  773. end.