pdecl.pas 31 KB

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