pdecl.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  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, allow_typed_const: 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,ngenutil,
  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,true);
  152. end;
  153. procedure consts_dec(in_structure, allow_typed_const: 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. if not allow_typed_const then
  197. begin
  198. Message(parser_e_no_typed_const);
  199. consume_all_until(_SEMICOLON);
  200. end;
  201. { set the blocktype first so a consume also supports a
  202. caret, to support const s : ^string = nil }
  203. block_type:=bt_const_type;
  204. consume(_COLON);
  205. read_anon_type(hdef,false);
  206. block_type:=bt_const;
  207. skipequal:=false;
  208. { create symbol }
  209. storetokenpos:=current_tokenpos;
  210. current_tokenpos:=filepos;
  211. if not (cs_typed_const_writable in current_settings.localswitches) then
  212. varspez:=vs_const
  213. else
  214. varspez:=vs_value;
  215. { if we are dealing with structure const then we need to handle it as a
  216. structure static variable: create a symbol in unit symtable and a reference
  217. to it from the structure or linking will fail }
  218. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  219. begin
  220. { generate the symbol which reserves the space }
  221. static_name:=lower(generate_nested_name(symtablestack.top,'_'))+'_'+orgname;
  222. {$ifndef jvm}
  223. sym:=tstaticvarsym.create(internal_static_field_name(static_name),varspez,hdef,[]);
  224. include(sym.symoptions,sp_internal);
  225. tabstractrecordsymtable(symtablestack.top).get_unit_symtable.insert(sym);
  226. {$else not jvm}
  227. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  228. symtablestack.top.insert(sym);
  229. orgname:=static_name;
  230. {$endif not jvm}
  231. { generate the symbol for the access }
  232. sl:=tpropaccesslist.create;
  233. sl.addsym(sl_load,sym);
  234. tmp:=tabsolutevarsym.create_ref(orgname,hdef,sl);
  235. tmp.visibility:=symtablestack.top.currentvisibility;
  236. symtablestack.top.insert(tmp);
  237. end
  238. else
  239. begin
  240. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  241. sym.visibility:=symtablestack.top.currentvisibility;
  242. symtablestack.top.insert(sym);
  243. end;
  244. current_tokenpos:=storetokenpos;
  245. { procvar can have proc directives, but not type references }
  246. if (hdef.typ=procvardef) and
  247. (hdef.typesym=nil) then
  248. begin
  249. { support p : procedure;stdcall=nil; }
  250. if try_to_consume(_SEMICOLON) then
  251. begin
  252. if check_proc_directive(true) then
  253. parse_var_proc_directives(sym)
  254. else
  255. begin
  256. Message(parser_e_proc_directive_expected);
  257. skipequal:=true;
  258. end;
  259. end
  260. else
  261. { support p : procedure stdcall=nil; }
  262. begin
  263. if check_proc_directive(true) then
  264. parse_var_proc_directives(sym);
  265. end;
  266. { add default calling convention }
  267. handle_calling_convention(tabstractprocdef(hdef));
  268. end;
  269. if not skipequal then
  270. begin
  271. { get init value }
  272. consume(_EQ);
  273. if (cs_typed_const_writable in current_settings.localswitches) then
  274. tclist:=current_asmdata.asmlists[al_typedconsts]
  275. else
  276. tclist:=current_asmdata.asmlists[al_rotypedconsts];
  277. read_typed_const(tclist,tstaticvarsym(sym),in_structure);
  278. end;
  279. end;
  280. else
  281. { generate an error }
  282. consume(_EQ);
  283. end;
  284. until (token<>_ID) or
  285. (in_structure and
  286. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  287. ((m_final_fields in current_settings.modeswitches) and
  288. (idtoken=_FINAL))));
  289. block_type:=old_block_type;
  290. end;
  291. procedure label_dec;
  292. var
  293. labelsym : tlabelsym;
  294. begin
  295. consume(_LABEL);
  296. if not(cs_support_goto in current_settings.moduleswitches) then
  297. Message(sym_e_goto_and_label_not_supported);
  298. repeat
  299. if not(token in [_ID,_INTCONST]) then
  300. consume(_ID)
  301. else
  302. begin
  303. if token=_ID then
  304. labelsym:=tlabelsym.create(orgpattern)
  305. else
  306. labelsym:=tlabelsym.create(pattern);
  307. symtablestack.top.insert(labelsym);
  308. if m_non_local_goto in current_settings.modeswitches then
  309. begin
  310. if symtablestack.top.symtabletype=localsymtable then
  311. begin
  312. labelsym.jumpbuf:=tlocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  313. symtablestack.top.insert(labelsym.jumpbuf);
  314. end
  315. else
  316. begin
  317. labelsym.jumpbuf:=tstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  318. symtablestack.top.insert(labelsym.jumpbuf);
  319. cnodeutils.insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  320. end;
  321. include(labelsym.jumpbuf.symoptions,sp_internal);
  322. { the buffer will be setup later, but avoid a hint }
  323. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  324. end;
  325. consume(token);
  326. end;
  327. if token<>_SEMICOLON then consume(_COMMA);
  328. until not(token in [_ID,_INTCONST]);
  329. consume(_SEMICOLON);
  330. end;
  331. function parse_generic_parameters:TFPObjectList;
  332. var
  333. generictype : ttypesym;
  334. begin
  335. result:=TFPObjectList.Create(false);
  336. repeat
  337. if token=_ID then
  338. begin
  339. generictype:=ttypesym.create(orgpattern,cundefinedtype);
  340. include(generictype.symoptions,sp_generic_para);
  341. result.add(generictype);
  342. end;
  343. consume(_ID);
  344. until not try_to_consume(_COMMA) ;
  345. end;
  346. procedure insert_generic_parameter_types(def:tstoreddef;genericdef:tstoreddef;genericlist:TFPObjectList);
  347. var
  348. i: longint;
  349. generictype: ttypesym;
  350. st: tsymtable;
  351. begin
  352. def.genericdef:=genericdef;
  353. if not assigned(genericlist) then
  354. exit;
  355. case def.typ of
  356. recorddef,objectdef: st:=tabstractrecorddef(def).symtable;
  357. arraydef: st:=tarraydef(def).symtable;
  358. procvardef,procdef: st:=tabstractprocdef(def).parast;
  359. else
  360. internalerror(201101020);
  361. end;
  362. for i:=0 to genericlist.count-1 do
  363. begin
  364. generictype:=ttypesym(genericlist[i]);
  365. if generictype.typedef.typ=undefineddef then
  366. include(def.defoptions,df_generic)
  367. else
  368. include(def.defoptions,df_specialization);
  369. st.insert(generictype);
  370. end;
  371. end;
  372. procedure types_dec(in_structure: boolean);
  373. procedure finalize_class_external_status(od: tobjectdef);
  374. begin
  375. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  376. begin
  377. { formal definition: x = objcclass external; }
  378. exclude(od.objectoptions,oo_is_forward);
  379. include(od.objectoptions,oo_is_formal);
  380. end;
  381. end;
  382. var
  383. typename,orgtypename : TIDString;
  384. newtype : ttypesym;
  385. sym : tsym;
  386. hdef : tdef;
  387. defpos,storetokenpos : tfileposinfo;
  388. old_block_type : tblock_type;
  389. old_checkforwarddefs: TFPObjectList;
  390. objecttype : tobjecttyp;
  391. isgeneric,
  392. isunique,
  393. istyperenaming : boolean;
  394. generictypelist : TFPObjectList;
  395. generictokenbuf : tdynamicarray;
  396. vmtbuilder : TVMTBuilder;
  397. begin
  398. old_block_type:=block_type;
  399. { save unit container of forward declarations -
  400. we can be inside nested class type block }
  401. old_checkforwarddefs:=current_module.checkforwarddefs;
  402. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  403. block_type:=bt_type;
  404. repeat
  405. defpos:=current_tokenpos;
  406. istyperenaming:=false;
  407. generictypelist:=nil;
  408. generictokenbuf:=nil;
  409. { fpc generic declaration? }
  410. isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  411. typename:=pattern;
  412. orgtypename:=orgpattern;
  413. consume(_ID);
  414. { delphi generic declaration? }
  415. if (m_delphi in current_settings.modeswitches) then
  416. isgeneric:=token=_LSHARPBRACKET;
  417. { Generic type declaration? }
  418. if isgeneric then
  419. begin
  420. if assigned(current_genericdef) then
  421. Message(parser_f_no_generic_inside_generic);
  422. consume(_LSHARPBRACKET);
  423. generictypelist:=parse_generic_parameters;
  424. consume(_RSHARPBRACKET);
  425. end;
  426. consume(_EQ);
  427. { support 'ttype=type word' syntax }
  428. isunique:=try_to_consume(_TYPE);
  429. { MacPas object model is more like Delphi's than like TP's, but }
  430. { uses the object keyword instead of class }
  431. if (m_mac in current_settings.modeswitches) and
  432. (token = _OBJECT) then
  433. token := _CLASS;
  434. { Start recording a generic template }
  435. if assigned(generictypelist) then
  436. begin
  437. generictokenbuf:=tdynamicarray.create(256);
  438. current_scanner.startrecordtokens(generictokenbuf);
  439. end;
  440. { is the type already defined? -- must be in the current symtable,
  441. not in a nested symtable or one higher up the stack -> don't
  442. use searchsym & frinds! }
  443. sym:=tsym(symtablestack.top.find(typename));
  444. newtype:=nil;
  445. { found a symbol with this name? }
  446. if assigned(sym) then
  447. begin
  448. if (sym.typ=typesym) then
  449. begin
  450. if ((token=_CLASS) or
  451. (token=_INTERFACE) or
  452. (token=_DISPINTERFACE) or
  453. (token=_OBJCCLASS) or
  454. (token=_OBJCPROTOCOL) or
  455. (token=_OBJCCATEGORY)) and
  456. (assigned(ttypesym(sym).typedef)) and
  457. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  458. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  459. begin
  460. case token of
  461. _CLASS :
  462. objecttype:=default_class_type;
  463. _INTERFACE :
  464. case current_settings.interfacetype of
  465. it_interfacecom:
  466. objecttype:=odt_interfacecom;
  467. it_interfacecorba:
  468. objecttype:=odt_interfacecorba;
  469. it_interfacejava:
  470. objecttype:=odt_interfacejava;
  471. else
  472. internalerror(2010122611);
  473. end;
  474. _DISPINTERFACE :
  475. objecttype:=odt_dispinterface;
  476. _OBJCCLASS,
  477. _OBJCCATEGORY :
  478. objecttype:=odt_objcclass;
  479. _OBJCPROTOCOL :
  480. objecttype:=odt_objcprotocol;
  481. else
  482. internalerror(200811072);
  483. end;
  484. consume(token);
  485. { we can ignore the result, the definition is modified }
  486. object_dec(objecttype,orgtypename,nil,nil,tobjectdef(ttypesym(sym).typedef),ht_none);
  487. newtype:=ttypesym(sym);
  488. hdef:=newtype.typedef;
  489. end
  490. else
  491. message1(parser_h_type_redef,orgtypename);
  492. end;
  493. end;
  494. { no old type reused ? Then insert this new type }
  495. if not assigned(newtype) then
  496. begin
  497. { insert the new type first with an errordef, so that
  498. referencing the type before it's really set it
  499. will give an error (PFV) }
  500. hdef:=generrordef;
  501. storetokenpos:=current_tokenpos;
  502. newtype:=ttypesym.create(orgtypename,hdef);
  503. newtype.visibility:=symtablestack.top.currentvisibility;
  504. symtablestack.top.insert(newtype);
  505. current_tokenpos:=defpos;
  506. current_tokenpos:=storetokenpos;
  507. { read the type definition }
  508. read_named_type(hdef,orgtypename,nil,generictypelist,false);
  509. { update the definition of the type }
  510. if assigned(hdef) then
  511. begin
  512. if assigned(hdef.typesym) then
  513. istyperenaming:=true;
  514. if isunique then
  515. begin
  516. if is_objc_class_or_protocol(hdef) or
  517. is_java_class_or_interface(hdef) then
  518. Message(parser_e_unique_unsupported);
  519. hdef:=tstoreddef(hdef).getcopy;
  520. { fix name, it is used e.g. for tables }
  521. if is_class_or_interface_or_dispinterface(hdef) then
  522. with tobjectdef(hdef) do
  523. begin
  524. stringdispose(objname);
  525. stringdispose(objrealname);
  526. objrealname:=stringdup(orgtypename);
  527. objname:=stringdup(upper(orgtypename));
  528. end;
  529. include(hdef.defoptions,df_unique);
  530. if (hdef.typ in [pointerdef,classrefdef]) and
  531. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  532. current_module.checkforwarddefs.add(hdef);
  533. end;
  534. if not assigned(hdef.typesym) then
  535. hdef.typesym:=newtype;
  536. end;
  537. newtype.typedef:=hdef;
  538. { KAZ: handle TGUID declaration in system unit }
  539. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  540. (typename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  541. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  542. rec_tguid:=trecorddef(hdef);
  543. end;
  544. if assigned(hdef) then
  545. begin
  546. case hdef.typ of
  547. pointerdef :
  548. begin
  549. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  550. consume(_SEMICOLON);
  551. if try_to_consume(_FAR) then
  552. begin
  553. tpointerdef(hdef).is_far:=true;
  554. consume(_SEMICOLON);
  555. end;
  556. end;
  557. procvardef :
  558. begin
  559. { in case of type renaming, don't parse proc directives }
  560. if istyperenaming then
  561. begin
  562. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  563. consume(_SEMICOLON);
  564. end
  565. else
  566. begin
  567. if not check_proc_directive(true) then
  568. begin
  569. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  570. consume(_SEMICOLON);
  571. end;
  572. parse_var_proc_directives(tsym(newtype));
  573. handle_calling_convention(tprocvardef(hdef));
  574. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  575. consume(_SEMICOLON);
  576. end;
  577. end;
  578. objectdef :
  579. begin
  580. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  581. consume(_SEMICOLON);
  582. { change a forward and external class declaration into
  583. formal external definition, so the compiler does not
  584. expect an real definition later }
  585. if is_objc_class_or_protocol(hdef) or
  586. is_java_class_or_interface(hdef) then
  587. finalize_class_external_status(tobjectdef(hdef));
  588. { Build VMT indexes, skip for type renaming and forward classes }
  589. if (hdef.typesym=newtype) and
  590. not(oo_is_forward in tobjectdef(hdef).objectoptions) and
  591. not(df_generic in hdef.defoptions) then
  592. begin
  593. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  594. vmtbuilder.generate_vmt;
  595. vmtbuilder.free;
  596. end;
  597. { In case of an objcclass, verify that all methods have a message
  598. name set. We only check this now, because message names can be set
  599. during the protocol (interface) mapping. At the same time, set the
  600. mangled names (these depend on the "external" name of the class),
  601. and mark private fields of external classes as "used" (to avoid
  602. bogus notes about them being unused)
  603. }
  604. { watch out for crashes in case of errors }
  605. if is_objc_class_or_protocol(hdef) and
  606. (not is_objccategory(hdef) or
  607. assigned(tobjectdef(hdef).childof)) then
  608. tobjectdef(hdef).finish_objc_data;
  609. if is_cppclass(hdef) then
  610. tobjectdef(hdef).finish_cpp_data;
  611. end;
  612. recorddef :
  613. begin
  614. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  615. consume(_SEMICOLON);
  616. end;
  617. else
  618. begin
  619. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  620. consume(_SEMICOLON);
  621. end;
  622. end;
  623. end;
  624. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  625. or is_objectpascal_helper(hdef)) then
  626. message(parser_e_cant_create_generics_of_this_type);
  627. { Stop recording a generic template }
  628. if assigned(generictypelist) then
  629. begin
  630. current_scanner.stoprecordtokens;
  631. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  632. { Generic is never a type renaming }
  633. hdef.typesym:=newtype;
  634. generictypelist.free;
  635. end;
  636. until (token<>_ID) or
  637. (in_structure and
  638. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  639. ((m_final_fields in current_settings.modeswitches) and
  640. (idtoken=_FINAL))));
  641. { resolve type block forward declarations and restore a unit
  642. container for them }
  643. resolve_forward_types;
  644. current_module.checkforwarddefs.free;
  645. current_module.checkforwarddefs:=old_checkforwarddefs;
  646. block_type:=old_block_type;
  647. end;
  648. { reads a type declaration to the symbol table }
  649. procedure type_dec;
  650. begin
  651. consume(_TYPE);
  652. types_dec(false);
  653. end;
  654. procedure var_dec;
  655. { parses variable declarations and inserts them in }
  656. { the top symbol table of symtablestack }
  657. begin
  658. consume(_VAR);
  659. read_var_decls([]);
  660. end;
  661. procedure property_dec(is_classpropery: boolean);
  662. var
  663. old_block_type : tblock_type;
  664. begin
  665. consume(_PROPERTY);
  666. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  667. message(parser_e_resourcestring_only_sg);
  668. old_block_type:=block_type;
  669. block_type:=bt_const;
  670. repeat
  671. read_property_dec(is_classpropery, nil);
  672. consume(_SEMICOLON);
  673. until token<>_ID;
  674. block_type:=old_block_type;
  675. end;
  676. procedure threadvar_dec;
  677. { parses thread variable declarations and inserts them in }
  678. { the top symbol table of symtablestack }
  679. begin
  680. consume(_THREADVAR);
  681. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  682. message(parser_e_threadvars_only_sg);
  683. read_var_decls([vd_threadvar]);
  684. end;
  685. procedure resourcestring_dec;
  686. var
  687. orgname : TIDString;
  688. p : tnode;
  689. dummysymoptions : tsymoptions;
  690. deprecatedmsg : pshortstring;
  691. storetokenpos,filepos : tfileposinfo;
  692. old_block_type : tblock_type;
  693. sp : pchar;
  694. sym : tsym;
  695. begin
  696. consume(_RESOURCESTRING);
  697. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  698. message(parser_e_resourcestring_only_sg);
  699. old_block_type:=block_type;
  700. block_type:=bt_const;
  701. repeat
  702. orgname:=orgpattern;
  703. filepos:=current_tokenpos;
  704. consume(_ID);
  705. case token of
  706. _EQ:
  707. begin
  708. consume(_EQ);
  709. p:=comp_expr(true,false);
  710. storetokenpos:=current_tokenpos;
  711. current_tokenpos:=filepos;
  712. sym:=nil;
  713. case p.nodetype of
  714. ordconstn:
  715. begin
  716. if is_constcharnode(p) then
  717. begin
  718. getmem(sp,2);
  719. sp[0]:=chr(tordconstnode(p).value.svalue);
  720. sp[1]:=#0;
  721. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  722. end
  723. else
  724. Message(parser_e_illegal_expression);
  725. end;
  726. stringconstn:
  727. with Tstringconstnode(p) do
  728. begin
  729. getmem(sp,len+1);
  730. move(value_str^,sp^,len+1);
  731. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  732. end;
  733. else
  734. Message(parser_e_illegal_expression);
  735. end;
  736. current_tokenpos:=storetokenpos;
  737. { Support hint directives }
  738. dummysymoptions:=[];
  739. deprecatedmsg:=nil;
  740. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  741. if assigned(sym) then
  742. begin
  743. sym.symoptions:=sym.symoptions+dummysymoptions;
  744. sym.deprecatedmsg:=deprecatedmsg;
  745. symtablestack.top.insert(sym);
  746. end
  747. else
  748. stringdispose(deprecatedmsg);
  749. consume(_SEMICOLON);
  750. p.free;
  751. end;
  752. else consume(_EQ);
  753. end;
  754. until token<>_ID;
  755. block_type:=old_block_type;
  756. end;
  757. end.