pdecl.pas 40 KB

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