pdecl.pas 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  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; out nodetype: tnodetype):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;
  38. procedure resourcestring_dec;
  39. implementation
  40. uses
  41. { common }
  42. cutils,
  43. { global }
  44. globals,tokens,verbose,widestr,constexp,
  45. systems,aasmdata,fmodule,
  46. { symtable }
  47. symconst,symbase,symtype,symtable,symcreat,defutil,
  48. { pass 1 }
  49. htypechk,ninl,ncon,nobj,ngenutil,
  50. { parser }
  51. scanner,
  52. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,pgenutil,
  53. {$ifdef jvm}
  54. pjvm,
  55. {$endif}
  56. { cpu-information }
  57. cpuinfo
  58. ;
  59. function readconstant(const orgname:string;const filepos:tfileposinfo; out nodetype: tnodetype):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. nodetype:=p.nodetype;
  76. storetokenpos:=current_tokenpos;
  77. current_tokenpos:=filepos;
  78. case p.nodetype of
  79. ordconstn:
  80. begin
  81. if p.resultdef.typ=pointerdef then
  82. hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  83. else
  84. hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  85. end;
  86. stringconstn:
  87. begin
  88. if is_wide_or_unicode_string(p.resultdef) then
  89. begin
  90. initwidestring(pw);
  91. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  92. hp:=tconstsym.create_wstring(orgname,constwstring,pw);
  93. end
  94. else
  95. begin
  96. getmem(sp,tstringconstnode(p).len+1);
  97. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  98. hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
  99. end;
  100. end;
  101. realconstn :
  102. begin
  103. new(pd);
  104. pd^:=trealconstnode(p).value_real;
  105. hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  106. end;
  107. setconstn :
  108. begin
  109. new(ps);
  110. ps^:=tsetconstnode(p).value_set^;
  111. hp:=tconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  112. end;
  113. pointerconstn :
  114. begin
  115. hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  116. end;
  117. niln :
  118. begin
  119. hp:=tconstsym.create_ord(orgname,constnil,0,p.resultdef);
  120. end;
  121. typen :
  122. begin
  123. if is_interface(p.resultdef) then
  124. begin
  125. if assigned(tobjectdef(p.resultdef).iidguid) then
  126. begin
  127. new(pg);
  128. pg^:=tobjectdef(p.resultdef).iidguid^;
  129. hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  130. end
  131. else
  132. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  133. end
  134. else
  135. Message(parser_e_illegal_expression);
  136. end;
  137. inlinen:
  138. begin
  139. { this situation only happens if a intrinsic is parsed that has a
  140. generic type as its argument. As we don't know certain
  141. information about the final type yet, we need to use safe
  142. values (mostly 0) }
  143. if not parse_generic then
  144. Message(parser_e_illegal_expression);
  145. case tinlinenode(p).inlinenumber of
  146. in_sizeof_x,
  147. in_bitsizeof_x:
  148. begin
  149. hp:=tconstsym.create_ord(orgname,constord,0,p.resultdef);
  150. end;
  151. { add other cases here if necessary }
  152. else
  153. Message(parser_e_illegal_expression);
  154. end;
  155. end;
  156. else
  157. Message(parser_e_illegal_expression);
  158. end;
  159. current_tokenpos:=storetokenpos;
  160. p.free;
  161. readconstant:=hp;
  162. end;
  163. procedure const_dec;
  164. begin
  165. consume(_CONST);
  166. consts_dec(false,true);
  167. end;
  168. procedure consts_dec(in_structure, allow_typed_const: boolean);
  169. var
  170. orgname : TIDString;
  171. hdef : tdef;
  172. sym : tsym;
  173. dummysymoptions : tsymoptions;
  174. deprecatedmsg : pshortstring;
  175. storetokenpos,filepos : tfileposinfo;
  176. nodetype : tnodetype;
  177. old_block_type : tblock_type;
  178. skipequal : boolean;
  179. tclist : tasmlist;
  180. varspez : tvarspez;
  181. begin
  182. old_block_type:=block_type;
  183. block_type:=bt_const;
  184. repeat
  185. orgname:=orgpattern;
  186. filepos:=current_tokenpos;
  187. consume(_ID);
  188. case token of
  189. _EQ:
  190. begin
  191. consume(_EQ);
  192. sym:=readconstant(orgname,filepos,nodetype);
  193. { Support hint directives }
  194. dummysymoptions:=[];
  195. deprecatedmsg:=nil;
  196. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  197. if assigned(sym) then
  198. begin
  199. sym.symoptions:=sym.symoptions+dummysymoptions;
  200. sym.deprecatedmsg:=deprecatedmsg;
  201. sym.visibility:=symtablestack.top.currentvisibility;
  202. symtablestack.top.insert(sym);
  203. {$ifdef jvm}
  204. { for the JVM target, some constants need to be
  205. initialized at run time (enums, sets) -> create fake
  206. typed const to do so }
  207. if assigned(tconstsym(sym).constdef) and
  208. (tconstsym(sym).constdef.typ in [enumdef,setdef]) then
  209. jvm_add_typed_const_initializer(tconstsym(sym));
  210. {$endif}
  211. end
  212. else
  213. stringdispose(deprecatedmsg);
  214. consume(_SEMICOLON);
  215. end;
  216. _COLON:
  217. begin
  218. if not allow_typed_const then
  219. begin
  220. Message(parser_e_no_typed_const);
  221. consume_all_until(_SEMICOLON);
  222. end;
  223. { set the blocktype first so a consume also supports a
  224. caret, to support const s : ^string = nil }
  225. block_type:=bt_const_type;
  226. consume(_COLON);
  227. read_anon_type(hdef,false);
  228. block_type:=bt_const;
  229. skipequal:=false;
  230. { create symbol }
  231. storetokenpos:=current_tokenpos;
  232. current_tokenpos:=filepos;
  233. if not (cs_typed_const_writable in current_settings.localswitches) then
  234. varspez:=vs_const
  235. else
  236. varspez:=vs_value;
  237. { if we are dealing with structure const then we need to handle it as a
  238. structure static variable: create a symbol in unit symtable and a reference
  239. to it from the structure or linking will fail }
  240. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  241. begin
  242. sym:=tfieldvarsym.create(orgname,varspez,hdef,[]);
  243. symtablestack.top.insert(sym);
  244. sym:=make_field_static(symtablestack.top,tfieldvarsym(sym));
  245. end
  246. else
  247. begin
  248. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  249. sym.visibility:=symtablestack.top.currentvisibility;
  250. symtablestack.top.insert(sym);
  251. end;
  252. current_tokenpos:=storetokenpos;
  253. { procvar can have proc directives, but not type references }
  254. if (hdef.typ=procvardef) and
  255. (hdef.typesym=nil) then
  256. begin
  257. { support p : procedure;stdcall=nil; }
  258. if try_to_consume(_SEMICOLON) then
  259. begin
  260. if check_proc_directive(true) then
  261. parse_var_proc_directives(sym)
  262. else
  263. begin
  264. Message(parser_e_proc_directive_expected);
  265. skipequal:=true;
  266. end;
  267. end
  268. else
  269. { support p : procedure stdcall=nil; }
  270. begin
  271. if check_proc_directive(true) then
  272. parse_var_proc_directives(sym);
  273. end;
  274. { add default calling convention }
  275. handle_calling_convention(tabstractprocdef(hdef));
  276. end;
  277. if not skipequal then
  278. begin
  279. { get init value }
  280. consume(_EQ);
  281. if (cs_typed_const_writable in current_settings.localswitches) then
  282. tclist:=current_asmdata.asmlists[al_typedconsts]
  283. else
  284. tclist:=current_asmdata.asmlists[al_rotypedconsts];
  285. read_typed_const(tclist,tstaticvarsym(sym),in_structure);
  286. end;
  287. end;
  288. else
  289. { generate an error }
  290. consume(_EQ);
  291. end;
  292. until (token<>_ID) or
  293. (in_structure and
  294. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  295. ((m_final_fields in current_settings.modeswitches) and
  296. (idtoken=_FINAL))));
  297. block_type:=old_block_type;
  298. end;
  299. procedure label_dec;
  300. var
  301. labelsym : tlabelsym;
  302. begin
  303. consume(_LABEL);
  304. if not(cs_support_goto in current_settings.moduleswitches) then
  305. Message(sym_e_goto_and_label_not_supported);
  306. repeat
  307. if not(token in [_ID,_INTCONST]) then
  308. consume(_ID)
  309. else
  310. begin
  311. if token=_ID then
  312. labelsym:=tlabelsym.create(orgpattern)
  313. else
  314. labelsym:=tlabelsym.create(pattern);
  315. symtablestack.top.insert(labelsym);
  316. if m_non_local_goto in current_settings.modeswitches then
  317. begin
  318. if symtablestack.top.symtabletype=localsymtable then
  319. begin
  320. labelsym.jumpbuf:=tlocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  321. symtablestack.top.insert(labelsym.jumpbuf);
  322. end
  323. else
  324. begin
  325. labelsym.jumpbuf:=tstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  326. symtablestack.top.insert(labelsym.jumpbuf);
  327. cnodeutils.insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  328. end;
  329. include(labelsym.jumpbuf.symoptions,sp_internal);
  330. { the buffer will be setup later, but avoid a hint }
  331. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  332. end;
  333. consume(token);
  334. end;
  335. if token<>_SEMICOLON then consume(_COMMA);
  336. until not(token in [_ID,_INTCONST]);
  337. consume(_SEMICOLON);
  338. end;
  339. procedure types_dec(in_structure: boolean);
  340. function determine_generic_def(name:tidstring):tstoreddef;
  341. var
  342. hashedid : THashedIDString;
  343. pd : tprocdef;
  344. sym : tsym;
  345. begin
  346. result:=nil;
  347. { check whether this is a declaration of a type inside a
  348. specialization }
  349. if assigned(current_structdef) and
  350. (df_specialization in current_structdef.defoptions) then
  351. begin
  352. if not assigned(current_structdef.genericdef) or
  353. not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
  354. internalerror(2011052301);
  355. hashedid.id:=name;
  356. { we could be inside a method of the specialization
  357. instead of its declaration, so check that first (as
  358. local nested types aren't allowed we don't need to
  359. walk the symtablestack to find the localsymtable) }
  360. if symtablestack.top.symtabletype=localsymtable then
  361. begin
  362. { we are in a method }
  363. if not assigned(symtablestack.top.defowner) or
  364. (symtablestack.top.defowner.typ<>procdef) then
  365. internalerror(2011120701);
  366. pd:=tprocdef(symtablestack.top.defowner);
  367. if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
  368. internalerror(2011120702);
  369. sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
  370. end
  371. else
  372. sym:=nil;
  373. if not assigned(sym) or not (sym.typ=typesym) then
  374. begin
  375. { now search in the declaration of the generic }
  376. sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
  377. if not assigned(sym) or not (sym.typ=typesym) then
  378. internalerror(2011052302);
  379. end;
  380. { use the corresponding type in the generic's symtable as
  381. genericdef for the specialized type }
  382. result:=tstoreddef(ttypesym(sym).typedef);
  383. end;
  384. end;
  385. procedure finalize_class_external_status(od: tobjectdef);
  386. begin
  387. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  388. begin
  389. { formal definition: x = objcclass external; }
  390. exclude(od.objectoptions,oo_is_forward);
  391. include(od.objectoptions,oo_is_formal);
  392. end;
  393. end;
  394. var
  395. typename,orgtypename,
  396. gentypename,genorgtypename : TIDString;
  397. newtype : ttypesym;
  398. sym : tsym;
  399. hdef : tdef;
  400. defpos,storetokenpos : tfileposinfo;
  401. old_block_type : tblock_type;
  402. old_checkforwarddefs: TFPObjectList;
  403. objecttype : tobjecttyp;
  404. isgeneric,
  405. isunique,
  406. istyperenaming : boolean;
  407. generictypelist : TFPObjectList;
  408. generictokenbuf : tdynamicarray;
  409. vmtbuilder : TVMTBuilder;
  410. p:tnode;
  411. gendef : tstoreddef;
  412. s : shortstring;
  413. {$ifdef x86}
  414. segment_register: string;
  415. {$endif x86}
  416. begin
  417. old_block_type:=block_type;
  418. { save unit container of forward declarations -
  419. we can be inside nested class type block }
  420. old_checkforwarddefs:=current_module.checkforwarddefs;
  421. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  422. block_type:=bt_type;
  423. repeat
  424. defpos:=current_tokenpos;
  425. istyperenaming:=false;
  426. generictypelist:=nil;
  427. generictokenbuf:=nil;
  428. { fpc generic declaration? }
  429. isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  430. typename:=pattern;
  431. orgtypename:=orgpattern;
  432. consume(_ID);
  433. { delphi generic declaration? }
  434. if (m_delphi in current_settings.modeswitches) then
  435. isgeneric:=token=_LSHARPBRACKET;
  436. { Generic type declaration? }
  437. if isgeneric then
  438. begin
  439. if assigned(current_genericdef) then
  440. Message(parser_f_no_generic_inside_generic);
  441. consume(_LSHARPBRACKET);
  442. generictypelist:=parse_generic_parameters(true);
  443. consume(_RSHARPBRACKET);
  444. str(generictypelist.Count,s);
  445. gentypename:=typename+'$'+s;
  446. genorgtypename:=orgtypename+'$'+s;
  447. end
  448. else
  449. begin
  450. gentypename:=typename;
  451. genorgtypename:=orgtypename;
  452. end;
  453. consume(_EQ);
  454. { support 'ttype=type word' syntax }
  455. isunique:=try_to_consume(_TYPE);
  456. { MacPas object model is more like Delphi's than like TP's, but }
  457. { uses the object keyword instead of class }
  458. if (m_mac in current_settings.modeswitches) and
  459. (token = _OBJECT) then
  460. token := _CLASS;
  461. { Start recording a generic template }
  462. if assigned(generictypelist) then
  463. begin
  464. generictokenbuf:=tdynamicarray.create(256);
  465. current_scanner.startrecordtokens(generictokenbuf);
  466. end;
  467. { is the type already defined? -- must be in the current symtable,
  468. not in a nested symtable or one higher up the stack -> don't
  469. use searchsym & frinds! }
  470. sym:=tsym(symtablestack.top.find(gentypename));
  471. newtype:=nil;
  472. { found a symbol with this name? }
  473. if assigned(sym) then
  474. begin
  475. if (sym.typ=typesym) and
  476. { this should not be a symbol that was created by a generic
  477. that was declared earlier }
  478. not (
  479. (ttypesym(sym).typedef.typ=undefineddef) and
  480. (sp_generic_dummy in sym.symoptions)
  481. ) then
  482. begin
  483. if ((token=_CLASS) or
  484. (token=_INTERFACE) or
  485. (token=_DISPINTERFACE) or
  486. (token=_OBJCCLASS) or
  487. (token=_OBJCPROTOCOL) or
  488. (token=_OBJCCATEGORY)) and
  489. (assigned(ttypesym(sym).typedef)) and
  490. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  491. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  492. begin
  493. case token of
  494. _CLASS :
  495. objecttype:=default_class_type;
  496. _INTERFACE :
  497. case current_settings.interfacetype of
  498. it_interfacecom:
  499. objecttype:=odt_interfacecom;
  500. it_interfacecorba:
  501. objecttype:=odt_interfacecorba;
  502. it_interfacejava:
  503. objecttype:=odt_interfacejava;
  504. else
  505. internalerror(2010122611);
  506. end;
  507. _DISPINTERFACE :
  508. objecttype:=odt_dispinterface;
  509. _OBJCCLASS,
  510. _OBJCCATEGORY :
  511. objecttype:=odt_objcclass;
  512. _OBJCPROTOCOL :
  513. objecttype:=odt_objcprotocol;
  514. else
  515. internalerror(200811072);
  516. end;
  517. consume(token);
  518. { determine the generic def in case we are in a nested type
  519. of a specialization }
  520. gendef:=determine_generic_def(gentypename);
  521. { we can ignore the result, the definition is modified }
  522. object_dec(objecttype,genorgtypename,newtype,gendef,generictypelist,tobjectdef(ttypesym(sym).typedef),ht_none);
  523. newtype:=ttypesym(sym);
  524. hdef:=newtype.typedef;
  525. end
  526. else
  527. message1(parser_h_type_redef,genorgtypename);
  528. end;
  529. end;
  530. { no old type reused ? Then insert this new type }
  531. if not assigned(newtype) then
  532. begin
  533. { insert the new type first with an errordef, so that
  534. referencing the type before it's really set it
  535. will give an error (PFV) }
  536. hdef:=generrordef;
  537. gendef:=nil;
  538. storetokenpos:=current_tokenpos;
  539. if isgeneric then
  540. begin
  541. { for generics we need to check whether a non-generic type
  542. already exists and if not we need to insert a symbol with
  543. the non-generic name (available in (org)typename) that is a
  544. undefineddef, so that inline specializations can be used }
  545. sym:=tsym(symtablestack.top.Find(typename));
  546. if not assigned(sym) then
  547. begin
  548. sym:=ttypesym.create(orgtypename,tundefineddef.create);
  549. Include(sym.symoptions,sp_generic_dummy);
  550. ttypesym(sym).typedef.typesym:=sym;
  551. sym.visibility:=symtablestack.top.currentvisibility;
  552. symtablestack.top.insert(sym);
  553. ttypesym(sym).typedef.owner:=sym.owner;
  554. end
  555. else
  556. { this is not allowed in non-Delphi modes }
  557. if not (m_delphi in current_settings.modeswitches) then
  558. Message1(sym_e_duplicate_id,genorgtypename)
  559. else
  560. { we need to find this symbol even if it's a variable or
  561. something else when doing an inline specialization }
  562. Include(sym.symoptions,sp_generic_dummy);
  563. end
  564. else
  565. begin
  566. if assigned(sym) and (sym.typ=typesym) and
  567. (ttypesym(sym).typedef.typ=undefineddef) and
  568. (sp_generic_dummy in sym.symoptions) then
  569. begin
  570. { this is a symbol that was added by an earlier generic
  571. declaration, reuse it }
  572. newtype:=ttypesym(sym);
  573. newtype.typedef:=hdef;
  574. sym:=nil;
  575. end;
  576. { determine the generic def in case we are in a nested type
  577. of a specialization }
  578. gendef:=determine_generic_def(gentypename);
  579. end;
  580. { insert a new type if we don't reuse an existing symbol }
  581. if not assigned(newtype) then
  582. begin
  583. newtype:=ttypesym.create(genorgtypename,hdef);
  584. newtype.visibility:=symtablestack.top.currentvisibility;
  585. symtablestack.top.insert(newtype);
  586. end;
  587. current_tokenpos:=defpos;
  588. current_tokenpos:=storetokenpos;
  589. { read the type definition }
  590. read_named_type(hdef,newtype,gendef,generictypelist,false,isunique);
  591. { update the definition of the type }
  592. if assigned(hdef) then
  593. begin
  594. if df_generic in hdef.defoptions then
  595. { flag parent symtables that they now contain a generic }
  596. hdef.owner.includeoption(sto_has_generic);
  597. if assigned(hdef.typesym) then
  598. begin
  599. istyperenaming:=true;
  600. include(newtype.symoptions,sp_explicitrename);
  601. end;
  602. if isunique then
  603. begin
  604. if is_objc_class_or_protocol(hdef) or
  605. is_java_class_or_interface(hdef) then
  606. Message(parser_e_unique_unsupported);
  607. hdef:=tstoreddef(hdef).getcopy;
  608. { check if it is an ansistirng(codepage) declaration }
  609. if is_ansistring(hdef) and try_to_consume(_LKLAMMER) then
  610. begin
  611. p:=comp_expr(true,false);
  612. consume(_RKLAMMER);
  613. if not is_constintnode(p) then
  614. begin
  615. Message(parser_e_illegal_expression);
  616. { error recovery }
  617. end
  618. else
  619. begin
  620. if (tordconstnode(p).value<0) or (tordconstnode(p).value>65535) then
  621. begin
  622. Message(parser_e_invalid_codepage);
  623. tordconstnode(p).value:=0;
  624. end;
  625. tstringdef(hdef).encoding:=int64(tordconstnode(p).value);
  626. end;
  627. p.free;
  628. end;
  629. { fix name, it is used e.g. for tables }
  630. if is_class_or_interface_or_dispinterface(hdef) then
  631. with tobjectdef(hdef) do
  632. begin
  633. stringdispose(objname);
  634. stringdispose(objrealname);
  635. objrealname:=stringdup(genorgtypename);
  636. objname:=stringdup(upper(genorgtypename));
  637. end;
  638. include(hdef.defoptions,df_unique);
  639. if (hdef.typ in [pointerdef,classrefdef]) and
  640. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  641. current_module.checkforwarddefs.add(hdef);
  642. end;
  643. if not assigned(hdef.typesym) then
  644. hdef.typesym:=newtype;
  645. end;
  646. { in non-Delphi modes we need a reference to the generic def
  647. without the generic suffix, so it can be found easily when
  648. parsing method implementations }
  649. if isgeneric and assigned(sym) and
  650. not (m_delphi in current_settings.modeswitches) and
  651. (ttypesym(sym).typedef.typ=undefineddef) then
  652. { don't free the undefineddef as the defids rely on the count
  653. of the defs in the def list of the module}
  654. ttypesym(sym).typedef:=hdef;
  655. newtype.typedef:=hdef;
  656. { KAZ: handle TGUID declaration in system unit }
  657. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  658. (gentypename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  659. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  660. rec_tguid:=trecorddef(hdef);
  661. end;
  662. if assigned(hdef) then
  663. begin
  664. case hdef.typ of
  665. pointerdef :
  666. begin
  667. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  668. consume(_SEMICOLON);
  669. {$ifdef x86}
  670. if try_to_consume(_FAR) then
  671. begin
  672. {$if defined(i8086)}
  673. tpointerdef(hdef).x86pointertyp:=x86pt_far;
  674. {$elseif defined(i386)}
  675. tpointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  676. {$elseif defined(x86_64)}
  677. { for compatibility with previous versions of fpc,
  678. far pointer = regular pointer on x86_64 }
  679. { TODO: decide if we still want to keep this }
  680. {$endif}
  681. consume(_SEMICOLON);
  682. end
  683. else
  684. if try_to_consume(_NEAR) then
  685. begin
  686. if token <> _SEMICOLON then
  687. begin
  688. segment_register:=get_stringconst;
  689. case UpCase(segment_register) of
  690. 'CS': tpointerdef(hdef).x86pointertyp:=x86pt_near_cs;
  691. 'DS': tpointerdef(hdef).x86pointertyp:=x86pt_near_ds;
  692. 'SS': tpointerdef(hdef).x86pointertyp:=x86pt_near_ss;
  693. 'ES': tpointerdef(hdef).x86pointertyp:=x86pt_near_es;
  694. 'FS': tpointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  695. 'GS': tpointerdef(hdef).x86pointertyp:=x86pt_near_gs;
  696. else
  697. Message(asmr_e_invalid_register);
  698. end;
  699. end
  700. else
  701. tpointerdef(hdef).x86pointertyp:=x86pt_near;
  702. consume(_SEMICOLON);
  703. end;
  704. {$else x86}
  705. { Previous versions of FPC support declaring a pointer as
  706. far even on non-x86 platforms.
  707. TODO: decide if we still want to keep this }
  708. if try_to_consume(_FAR) then
  709. begin
  710. consume(_SEMICOLON);
  711. end;
  712. {$endif x86}
  713. end;
  714. procvardef :
  715. begin
  716. { in case of type renaming, don't parse proc directives }
  717. if istyperenaming then
  718. begin
  719. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  720. consume(_SEMICOLON);
  721. end
  722. else
  723. begin
  724. if not check_proc_directive(true) then
  725. begin
  726. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  727. consume(_SEMICOLON);
  728. end;
  729. parse_var_proc_directives(tsym(newtype));
  730. handle_calling_convention(tprocvardef(hdef));
  731. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  732. consume(_SEMICOLON);
  733. end;
  734. end;
  735. objectdef :
  736. begin
  737. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  738. consume(_SEMICOLON);
  739. { change a forward and external class declaration into
  740. formal external definition, so the compiler does not
  741. expect an real definition later }
  742. if is_objc_class_or_protocol(hdef) or
  743. is_java_class_or_interface(hdef) then
  744. finalize_class_external_status(tobjectdef(hdef));
  745. { Build VMT indexes, skip for type renaming and forward classes }
  746. if (hdef.typesym=newtype) and
  747. not(oo_is_forward in tobjectdef(hdef).objectoptions) and
  748. not(df_generic in hdef.defoptions) then
  749. begin
  750. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  751. vmtbuilder.generate_vmt;
  752. vmtbuilder.free;
  753. end;
  754. { In case of an objcclass, verify that all methods have a message
  755. name set. We only check this now, because message names can be set
  756. during the protocol (interface) mapping. At the same time, set the
  757. mangled names (these depend on the "external" name of the class),
  758. and mark private fields of external classes as "used" (to avoid
  759. bogus notes about them being unused)
  760. }
  761. { watch out for crashes in case of errors }
  762. if is_objc_class_or_protocol(hdef) and
  763. (not is_objccategory(hdef) or
  764. assigned(tobjectdef(hdef).childof)) then
  765. tobjectdef(hdef).finish_objc_data;
  766. if is_cppclass(hdef) then
  767. tobjectdef(hdef).finish_cpp_data;
  768. end;
  769. recorddef :
  770. begin
  771. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  772. consume(_SEMICOLON);
  773. end;
  774. else
  775. begin
  776. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  777. consume(_SEMICOLON);
  778. end;
  779. end;
  780. end;
  781. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  782. or is_objectpascal_helper(hdef)) then
  783. message(parser_e_cant_create_generics_of_this_type);
  784. { Stop recording a generic template }
  785. if assigned(generictypelist) then
  786. begin
  787. current_scanner.stoprecordtokens;
  788. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  789. { Generic is never a type renaming }
  790. hdef.typesym:=newtype;
  791. generictypelist.free;
  792. end;
  793. until (token<>_ID) or
  794. (in_structure and
  795. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  796. ((m_final_fields in current_settings.modeswitches) and
  797. (idtoken=_FINAL))));
  798. { resolve type block forward declarations and restore a unit
  799. container for them }
  800. resolve_forward_types;
  801. current_module.checkforwarddefs.free;
  802. current_module.checkforwarddefs:=old_checkforwarddefs;
  803. block_type:=old_block_type;
  804. end;
  805. { reads a type declaration to the symbol table }
  806. procedure type_dec;
  807. begin
  808. consume(_TYPE);
  809. types_dec(false);
  810. end;
  811. procedure var_dec;
  812. { parses variable declarations and inserts them in }
  813. { the top symbol table of symtablestack }
  814. begin
  815. consume(_VAR);
  816. read_var_decls([]);
  817. end;
  818. procedure property_dec;
  819. { parses a global property (fpc mode feature) }
  820. var
  821. old_block_type: tblock_type;
  822. begin
  823. consume(_PROPERTY);
  824. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  825. message(parser_e_resourcestring_only_sg);
  826. old_block_type:=block_type;
  827. block_type:=bt_const;
  828. repeat
  829. read_property_dec(false, nil);
  830. consume(_SEMICOLON);
  831. until token<>_ID;
  832. block_type:=old_block_type;
  833. end;
  834. procedure threadvar_dec;
  835. { parses thread variable declarations and inserts them in }
  836. { the top symbol table of symtablestack }
  837. begin
  838. consume(_THREADVAR);
  839. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  840. message(parser_e_threadvars_only_sg);
  841. if f_threading in features then
  842. read_var_decls([vd_threadvar])
  843. else
  844. begin
  845. Message(parser_f_unsupported_feature);
  846. read_var_decls([]);
  847. end;
  848. end;
  849. procedure resourcestring_dec;
  850. var
  851. orgname : TIDString;
  852. p : tnode;
  853. dummysymoptions : tsymoptions;
  854. deprecatedmsg : pshortstring;
  855. storetokenpos,filepos : tfileposinfo;
  856. old_block_type : tblock_type;
  857. sp : pchar;
  858. sym : tsym;
  859. begin
  860. if target_info.system in systems_managed_vm then
  861. message(parser_e_feature_unsupported_for_vm);
  862. consume(_RESOURCESTRING);
  863. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  864. message(parser_e_resourcestring_only_sg);
  865. old_block_type:=block_type;
  866. block_type:=bt_const;
  867. repeat
  868. orgname:=orgpattern;
  869. filepos:=current_tokenpos;
  870. consume(_ID);
  871. case token of
  872. _EQ:
  873. begin
  874. consume(_EQ);
  875. p:=comp_expr(true,false);
  876. storetokenpos:=current_tokenpos;
  877. current_tokenpos:=filepos;
  878. sym:=nil;
  879. case p.nodetype of
  880. ordconstn:
  881. begin
  882. if is_constcharnode(p) then
  883. begin
  884. getmem(sp,2);
  885. sp[0]:=chr(tordconstnode(p).value.svalue);
  886. sp[1]:=#0;
  887. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  888. end
  889. else
  890. Message(parser_e_illegal_expression);
  891. end;
  892. stringconstn:
  893. with Tstringconstnode(p) do
  894. begin
  895. getmem(sp,len+1);
  896. move(value_str^,sp^,len+1);
  897. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  898. end;
  899. else
  900. Message(parser_e_illegal_expression);
  901. end;
  902. current_tokenpos:=storetokenpos;
  903. { Support hint directives }
  904. dummysymoptions:=[];
  905. deprecatedmsg:=nil;
  906. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  907. if assigned(sym) then
  908. begin
  909. sym.symoptions:=sym.symoptions+dummysymoptions;
  910. sym.deprecatedmsg:=deprecatedmsg;
  911. symtablestack.top.insert(sym);
  912. end
  913. else
  914. stringdispose(deprecatedmsg);
  915. consume(_SEMICOLON);
  916. p.free;
  917. end;
  918. else consume(_EQ);
  919. end;
  920. until token<>_ID;
  921. block_type:=old_block_type;
  922. end;
  923. end.