pdecl.pas 30 KB

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