pdecl.pas 46 KB

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