pdecl.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002
  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,symcpu,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:=cconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  83. else
  84. hp:=cconstsym.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:=cconstsym.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:=cconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len,p.resultdef)
  103. else
  104. hp:=cconstsym.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:=cconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  112. end;
  113. setconstn :
  114. begin
  115. new(ps);
  116. ps^:=tsetconstnode(p).value_set^;
  117. hp:=cconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  118. end;
  119. pointerconstn :
  120. begin
  121. hp:=cconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  122. end;
  123. niln :
  124. begin
  125. hp:=cconstsym.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:=cconstsym.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:=cconstsym.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:=cfieldvarsym.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:=cstaticvarsym.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:=clabelsym.create(orgpattern)
  322. else
  323. labelsym:=clabelsym.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:=clocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  330. symtablestack.top.insert(labelsym.jumpbuf);
  331. end
  332. else
  333. begin
  334. labelsym.jumpbuf:=cstaticvarsym.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 : tfphashobjectlist;
  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. hdef:=nil;
  433. repeat
  434. defpos:=current_tokenpos;
  435. istyperenaming:=false;
  436. generictypelist:=nil;
  437. generictokenbuf:=nil;
  438. { fpc generic declaration? }
  439. isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  440. typename:=pattern;
  441. orgtypename:=orgpattern;
  442. consume(_ID);
  443. { delphi generic declaration? }
  444. if (m_delphi in current_settings.modeswitches) then
  445. isgeneric:=token=_LSHARPBRACKET;
  446. { Generic type declaration? }
  447. if isgeneric then
  448. begin
  449. if assigned(current_genericdef) then
  450. Message(parser_f_no_generic_inside_generic);
  451. consume(_LSHARPBRACKET);
  452. generictypelist:=parse_generic_parameters(true);
  453. consume(_RSHARPBRACKET);
  454. str(generictypelist.Count,s);
  455. gentypename:=typename+'$'+s;
  456. genorgtypename:=orgtypename+'$'+s;
  457. end
  458. else
  459. begin
  460. gentypename:=typename;
  461. genorgtypename:=orgtypename;
  462. end;
  463. consume(_EQ);
  464. { support 'ttype=type word' syntax }
  465. isunique:=try_to_consume(_TYPE);
  466. { MacPas object model is more like Delphi's than like TP's, but }
  467. { uses the object keyword instead of class }
  468. if (m_mac in current_settings.modeswitches) and
  469. (token = _OBJECT) then
  470. token := _CLASS;
  471. { Start recording a generic template }
  472. if assigned(generictypelist) then
  473. begin
  474. generictokenbuf:=tdynamicarray.create(256);
  475. current_scanner.startrecordtokens(generictokenbuf);
  476. end;
  477. { is the type already defined? -- must be in the current symtable,
  478. not in a nested symtable or one higher up the stack -> don't
  479. use searchsym & frinds! }
  480. sym:=tsym(symtablestack.top.find(gentypename));
  481. newtype:=nil;
  482. { found a symbol with this name? }
  483. if assigned(sym) then
  484. begin
  485. if (sym.typ=typesym) and
  486. { this should not be a symbol that was created by a generic
  487. that was declared earlier }
  488. not (
  489. (ttypesym(sym).typedef.typ=undefineddef) and
  490. (sp_generic_dummy in sym.symoptions)
  491. ) then
  492. begin
  493. if ((token=_CLASS) or
  494. (token=_INTERFACE) or
  495. (token=_DISPINTERFACE) or
  496. (token=_OBJCCLASS) or
  497. (token=_OBJCPROTOCOL) or
  498. (token=_OBJCCATEGORY)) and
  499. (assigned(ttypesym(sym).typedef)) and
  500. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  501. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  502. begin
  503. case token of
  504. _CLASS :
  505. objecttype:=default_class_type;
  506. _INTERFACE :
  507. case current_settings.interfacetype of
  508. it_interfacecom:
  509. objecttype:=odt_interfacecom;
  510. it_interfacecorba:
  511. objecttype:=odt_interfacecorba;
  512. it_interfacejava:
  513. objecttype:=odt_interfacejava;
  514. else
  515. internalerror(2010122611);
  516. end;
  517. _DISPINTERFACE :
  518. objecttype:=odt_dispinterface;
  519. _OBJCCLASS,
  520. _OBJCCATEGORY :
  521. objecttype:=odt_objcclass;
  522. _OBJCPROTOCOL :
  523. objecttype:=odt_objcprotocol;
  524. else
  525. internalerror(200811072);
  526. end;
  527. consume(token);
  528. { determine the generic def in case we are in a nested type
  529. of a specialization }
  530. gendef:=determine_generic_def(gentypename);
  531. { we can ignore the result, the definition is modified }
  532. object_dec(objecttype,genorgtypename,newtype,gendef,generictypelist,tobjectdef(ttypesym(sym).typedef),ht_none);
  533. newtype:=ttypesym(sym);
  534. hdef:=newtype.typedef;
  535. end
  536. else
  537. message1(parser_h_type_redef,genorgtypename);
  538. end;
  539. end;
  540. { no old type reused ? Then insert this new type }
  541. if not assigned(newtype) then
  542. begin
  543. { insert the new type first with an errordef, so that
  544. referencing the type before it's really set it
  545. will give an error (PFV) }
  546. hdef:=generrordef;
  547. gendef:=nil;
  548. storetokenpos:=current_tokenpos;
  549. if isgeneric then
  550. begin
  551. { for generics we need to check whether a non-generic type
  552. already exists and if not we need to insert a symbol with
  553. the non-generic name (available in (org)typename) that is a
  554. undefineddef, so that inline specializations can be used }
  555. sym:=tsym(symtablestack.top.Find(typename));
  556. if not assigned(sym) then
  557. begin
  558. sym:=ctypesym.create(orgtypename,cundefineddef.create);
  559. Include(sym.symoptions,sp_generic_dummy);
  560. ttypesym(sym).typedef.typesym:=sym;
  561. sym.visibility:=symtablestack.top.currentvisibility;
  562. symtablestack.top.insert(sym);
  563. ttypesym(sym).typedef.owner:=sym.owner;
  564. end
  565. else
  566. { this is not allowed in non-Delphi modes }
  567. if not (m_delphi in current_settings.modeswitches) then
  568. Message1(sym_e_duplicate_id,genorgtypename)
  569. else
  570. { we need to find this symbol even if it's a variable or
  571. something else when doing an inline specialization }
  572. Include(sym.symoptions,sp_generic_dummy);
  573. end
  574. else
  575. begin
  576. if assigned(sym) and (sym.typ=typesym) and
  577. (ttypesym(sym).typedef.typ=undefineddef) and
  578. (sp_generic_dummy in sym.symoptions) then
  579. begin
  580. { this is a symbol that was added by an earlier generic
  581. declaration, reuse it }
  582. newtype:=ttypesym(sym);
  583. newtype.typedef:=hdef;
  584. sym:=nil;
  585. end;
  586. { determine the generic def in case we are in a nested type
  587. of a specialization }
  588. gendef:=determine_generic_def(gentypename);
  589. end;
  590. { insert a new type if we don't reuse an existing symbol }
  591. if not assigned(newtype) then
  592. begin
  593. newtype:=ctypesym.create(genorgtypename,hdef);
  594. newtype.visibility:=symtablestack.top.currentvisibility;
  595. symtablestack.top.insert(newtype);
  596. end;
  597. current_tokenpos:=defpos;
  598. current_tokenpos:=storetokenpos;
  599. { read the type definition }
  600. read_named_type(hdef,newtype,gendef,generictypelist,false,isunique);
  601. { update the definition of the type }
  602. if assigned(hdef) then
  603. begin
  604. if df_generic in hdef.defoptions then
  605. { flag parent symtables that they now contain a generic }
  606. hdef.owner.includeoption(sto_has_generic);
  607. if assigned(hdef.typesym) then
  608. begin
  609. istyperenaming:=true;
  610. include(newtype.symoptions,sp_explicitrename);
  611. end;
  612. if isunique then
  613. begin
  614. if is_objc_class_or_protocol(hdef) or
  615. is_java_class_or_interface(hdef) then
  616. Message(parser_e_unique_unsupported);
  617. hdef:=tstoreddef(hdef).getcopy;
  618. { check if it is an ansistirng(codepage) declaration }
  619. if is_ansistring(hdef) and try_to_consume(_LKLAMMER) then
  620. begin
  621. p:=comp_expr(true,false);
  622. consume(_RKLAMMER);
  623. if not is_constintnode(p) then
  624. begin
  625. Message(parser_e_illegal_expression);
  626. { error recovery }
  627. end
  628. else
  629. begin
  630. if (tordconstnode(p).value<0) or (tordconstnode(p).value>65535) then
  631. begin
  632. Message(parser_e_invalid_codepage);
  633. tordconstnode(p).value:=0;
  634. end;
  635. tstringdef(hdef).encoding:=int64(tordconstnode(p).value);
  636. end;
  637. p.free;
  638. end;
  639. { fix name, it is used e.g. for tables }
  640. if is_class_or_interface_or_dispinterface(hdef) then
  641. with tobjectdef(hdef) do
  642. begin
  643. stringdispose(objname);
  644. stringdispose(objrealname);
  645. objrealname:=stringdup(genorgtypename);
  646. objname:=stringdup(upper(genorgtypename));
  647. end;
  648. include(hdef.defoptions,df_unique);
  649. if (hdef.typ in [pointerdef,classrefdef]) and
  650. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  651. current_module.checkforwarddefs.add(hdef);
  652. end;
  653. if not assigned(hdef.typesym) then
  654. hdef.typesym:=newtype;
  655. end;
  656. { in non-Delphi modes we need a reference to the generic def
  657. without the generic suffix, so it can be found easily when
  658. parsing method implementations }
  659. if isgeneric and assigned(sym) and
  660. not (m_delphi in current_settings.modeswitches) and
  661. (ttypesym(sym).typedef.typ=undefineddef) then
  662. { don't free the undefineddef as the defids rely on the count
  663. of the defs in the def list of the module}
  664. ttypesym(sym).typedef:=hdef;
  665. newtype.typedef:=hdef;
  666. { KAZ: handle TGUID declaration in system unit }
  667. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  668. (gentypename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  669. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  670. rec_tguid:=trecorddef(hdef);
  671. end;
  672. if assigned(hdef) then
  673. begin
  674. case hdef.typ of
  675. pointerdef :
  676. begin
  677. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  678. consume(_SEMICOLON);
  679. {$ifdef x86}
  680. {$ifdef i8086}
  681. if try_to_consume(_HUGE) then
  682. begin
  683. tcpupointerdef(hdef).x86pointertyp:=x86pt_huge;
  684. consume(_SEMICOLON);
  685. end
  686. else
  687. {$endif i8086}
  688. if try_to_consume(_FAR) then
  689. begin
  690. {$if defined(i8086)}
  691. tcpupointerdef(hdef).x86pointertyp:=x86pt_far;
  692. {$elseif defined(i386)}
  693. tcpupointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  694. {$elseif defined(x86_64)}
  695. { for compatibility with previous versions of fpc,
  696. far pointer = regular pointer on x86_64 }
  697. Message1(parser_w_ptr_type_ignored,'FAR');
  698. {$endif}
  699. consume(_SEMICOLON);
  700. end
  701. else
  702. if try_to_consume(_NEAR) then
  703. begin
  704. if token <> _SEMICOLON then
  705. begin
  706. segment_register:=get_stringconst;
  707. case UpCase(segment_register) of
  708. 'CS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_cs;
  709. 'DS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_ds;
  710. 'SS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_ss;
  711. 'ES': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_es;
  712. 'FS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  713. 'GS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_gs;
  714. else
  715. Message(asmr_e_invalid_register);
  716. end;
  717. end
  718. else
  719. tcpupointerdef(hdef).x86pointertyp:=x86pt_near;
  720. consume(_SEMICOLON);
  721. end;
  722. {$else x86}
  723. { Previous versions of FPC support declaring a pointer as
  724. far even on non-x86 platforms. }
  725. if try_to_consume(_FAR) then
  726. begin
  727. Message1(parser_w_ptr_type_ignored,'FAR');
  728. consume(_SEMICOLON);
  729. end;
  730. {$endif x86}
  731. end;
  732. procvardef :
  733. begin
  734. { in case of type renaming, don't parse proc directives }
  735. if istyperenaming then
  736. begin
  737. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  738. consume(_SEMICOLON);
  739. end
  740. else
  741. begin
  742. if not check_proc_directive(true) then
  743. begin
  744. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  745. consume(_SEMICOLON);
  746. end;
  747. parse_var_proc_directives(tsym(newtype));
  748. handle_calling_convention(tprocvardef(hdef));
  749. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  750. consume(_SEMICOLON);
  751. end;
  752. end;
  753. objectdef :
  754. begin
  755. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  756. consume(_SEMICOLON);
  757. { change a forward and external class declaration into
  758. formal external definition, so the compiler does not
  759. expect an real definition later }
  760. if is_objc_class_or_protocol(hdef) or
  761. is_java_class_or_interface(hdef) then
  762. finalize_class_external_status(tobjectdef(hdef));
  763. { Build VMT indexes, skip for type renaming and forward classes }
  764. if (hdef.typesym=newtype) and
  765. not(oo_is_forward in tobjectdef(hdef).objectoptions) then
  766. begin
  767. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  768. vmtbuilder.generate_vmt;
  769. vmtbuilder.free;
  770. end;
  771. { In case of an objcclass, verify that all methods have a message
  772. name set. We only check this now, because message names can be set
  773. during the protocol (interface) mapping. At the same time, set the
  774. mangled names (these depend on the "external" name of the class),
  775. and mark private fields of external classes as "used" (to avoid
  776. bogus notes about them being unused)
  777. }
  778. { watch out for crashes in case of errors }
  779. if is_objc_class_or_protocol(hdef) and
  780. (not is_objccategory(hdef) or
  781. assigned(tobjectdef(hdef).childof)) then
  782. tobjectdef(hdef).finish_objc_data;
  783. if is_cppclass(hdef) then
  784. tobjectdef(hdef).finish_cpp_data;
  785. end;
  786. recorddef :
  787. begin
  788. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  789. consume(_SEMICOLON);
  790. end;
  791. else
  792. begin
  793. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  794. consume(_SEMICOLON);
  795. end;
  796. end;
  797. end;
  798. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  799. or is_objectpascal_helper(hdef)) then
  800. message(parser_e_cant_create_generics_of_this_type);
  801. { Stop recording a generic template }
  802. if assigned(generictypelist) then
  803. begin
  804. current_scanner.stoprecordtokens;
  805. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  806. { Generic is never a type renaming }
  807. hdef.typesym:=newtype;
  808. generictypelist.free;
  809. end;
  810. until (token<>_ID) or
  811. (in_structure and
  812. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  813. ((m_final_fields in current_settings.modeswitches) and
  814. (idtoken=_FINAL))));
  815. { resolve type block forward declarations and restore a unit
  816. container for them }
  817. resolve_forward_types;
  818. current_module.checkforwarddefs.free;
  819. current_module.checkforwarddefs:=old_checkforwarddefs;
  820. block_type:=old_block_type;
  821. end;
  822. { reads a type declaration to the symbol table }
  823. procedure type_dec;
  824. begin
  825. consume(_TYPE);
  826. types_dec(false);
  827. end;
  828. procedure var_dec;
  829. { parses variable declarations and inserts them in }
  830. { the top symbol table of symtablestack }
  831. begin
  832. consume(_VAR);
  833. read_var_decls([]);
  834. end;
  835. procedure property_dec;
  836. { parses a global property (fpc mode feature) }
  837. var
  838. old_block_type: tblock_type;
  839. begin
  840. consume(_PROPERTY);
  841. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  842. message(parser_e_property_only_sgr);
  843. old_block_type:=block_type;
  844. block_type:=bt_const;
  845. repeat
  846. read_property_dec(false, nil);
  847. consume(_SEMICOLON);
  848. until token<>_ID;
  849. block_type:=old_block_type;
  850. end;
  851. procedure threadvar_dec;
  852. { parses thread variable declarations and inserts them in }
  853. { the top symbol table of symtablestack }
  854. begin
  855. consume(_THREADVAR);
  856. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  857. message(parser_e_threadvars_only_sg);
  858. if f_threading in features then
  859. read_var_decls([vd_threadvar])
  860. else
  861. begin
  862. Message1(parser_f_unsupported_feature,featurestr[f_threading]);
  863. read_var_decls([]);
  864. end;
  865. end;
  866. procedure resourcestring_dec;
  867. var
  868. orgname : TIDString;
  869. p : tnode;
  870. dummysymoptions : tsymoptions;
  871. deprecatedmsg : pshortstring;
  872. storetokenpos,filepos : tfileposinfo;
  873. old_block_type : tblock_type;
  874. sp : pchar;
  875. sym : tsym;
  876. begin
  877. if target_info.system in systems_managed_vm then
  878. message(parser_e_feature_unsupported_for_vm);
  879. consume(_RESOURCESTRING);
  880. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  881. message(parser_e_resourcestring_only_sg);
  882. old_block_type:=block_type;
  883. block_type:=bt_const;
  884. repeat
  885. orgname:=orgpattern;
  886. filepos:=current_tokenpos;
  887. consume(_ID);
  888. case token of
  889. _EQ:
  890. begin
  891. consume(_EQ);
  892. p:=comp_expr(true,false);
  893. storetokenpos:=current_tokenpos;
  894. current_tokenpos:=filepos;
  895. sym:=nil;
  896. case p.nodetype of
  897. ordconstn:
  898. begin
  899. if is_constcharnode(p) then
  900. begin
  901. getmem(sp,2);
  902. sp[0]:=chr(tordconstnode(p).value.svalue);
  903. sp[1]:=#0;
  904. sym:=cconstsym.create_string(orgname,constresourcestring,sp,1,nil);
  905. end
  906. else
  907. Message(parser_e_illegal_expression);
  908. end;
  909. stringconstn:
  910. with Tstringconstnode(p) do
  911. begin
  912. { resourcestrings are currently always single byte }
  913. if cst_type in [cst_widestring,cst_unicodestring] then
  914. changestringtype(getansistringdef);
  915. getmem(sp,len+1);
  916. move(value_str^,sp^,len+1);
  917. sym:=cconstsym.create_string(orgname,constresourcestring,sp,len,nil);
  918. end;
  919. else
  920. Message(parser_e_illegal_expression);
  921. end;
  922. current_tokenpos:=storetokenpos;
  923. { Support hint directives }
  924. dummysymoptions:=[];
  925. deprecatedmsg:=nil;
  926. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  927. if assigned(sym) then
  928. begin
  929. sym.symoptions:=sym.symoptions+dummysymoptions;
  930. sym.deprecatedmsg:=deprecatedmsg;
  931. symtablestack.top.insert(sym);
  932. end
  933. else
  934. stringdispose(deprecatedmsg);
  935. consume(_SEMICOLON);
  936. p.free;
  937. end;
  938. else consume(_EQ);
  939. end;
  940. until token<>_ID;
  941. block_type:=old_block_type;
  942. end;
  943. end.