pdecl.pas 46 KB

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