pdecl.pas 31 KB

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