pdecl.pas 32 KB

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