pdecl.pas 32 KB

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