pdecl.pas 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  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,symtype,
  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;var rtti_attrs_def: trtti_attribute_list);
  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. procedure parse_rttiattributes(var rtti_attrs_def:trtti_attribute_list);
  40. function parse_forward_declaration(sym:tsym;gentypename,genorgtypename:tidstring;genericdef:tdef;generictypelist:tfphashobjectlist;out newtype:ttypesym):tdef;
  41. implementation
  42. uses
  43. SysUtils,
  44. { common }
  45. cutils,
  46. { global }
  47. globals,tokens,verbose,widestr,constexp,
  48. systems,aasmdata,fmodule,compinnr,
  49. { symtable }
  50. symconst,symbase,symcpu,symcreat,defutil,defcmp,symtable,symutil,
  51. { pass 1 }
  52. ninl,ncon,nobj,ngenutil,nld,nmem,ncal,pass_1,
  53. { parser }
  54. scanner,
  55. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,pgenutil,pparautl,
  56. procdefutil,
  57. {$ifdef jvm}
  58. pjvm,
  59. {$endif}
  60. { cpu-information }
  61. cpuinfo
  62. ;
  63. function is_system_custom_attribute_descendant(def:tdef):boolean;
  64. begin
  65. if not assigned(class_tcustomattribute) then
  66. class_tcustomattribute:=tobjectdef(search_system_type('TCUSTOMATTRIBUTE').typedef);
  67. Result:=def_is_related(def,class_tcustomattribute);
  68. end;
  69. function readconstant(const orgname:string;const filepos:tfileposinfo; out nodetype: tnodetype):tconstsym;
  70. var
  71. hp : tconstsym;
  72. p : tnode;
  73. ps : pconstset;
  74. pd : pbestreal;
  75. pg : pguid;
  76. sp : pchar;
  77. pw : pcompilerwidestring;
  78. storetokenpos : tfileposinfo;
  79. begin
  80. readconstant:=nil;
  81. if orgname='' then
  82. internalerror(9584582);
  83. hp:=nil;
  84. p:=comp_expr([ef_accept_equal]);
  85. nodetype:=p.nodetype;
  86. storetokenpos:=current_tokenpos;
  87. current_tokenpos:=filepos;
  88. case p.nodetype of
  89. ordconstn:
  90. begin
  91. if p.resultdef.typ=pointerdef then
  92. hp:=cconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  93. else
  94. hp:=cconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  95. end;
  96. stringconstn:
  97. begin
  98. if is_wide_or_unicode_string(p.resultdef) then
  99. begin
  100. initwidestring(pw);
  101. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  102. hp:=cconstsym.create_wstring(orgname,constwstring,pw);
  103. end
  104. else
  105. begin
  106. getmem(sp,tstringconstnode(p).len+1);
  107. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  108. { if a non-default ansistring code page has been specified,
  109. keep it }
  110. if is_ansistring(p.resultdef) and
  111. (tstringdef(p.resultdef).encoding<>0) then
  112. hp:=cconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len,p.resultdef)
  113. else
  114. hp:=cconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len,nil);
  115. end;
  116. end;
  117. realconstn :
  118. begin
  119. new(pd);
  120. pd^:=trealconstnode(p).value_real;
  121. hp:=cconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  122. end;
  123. setconstn :
  124. begin
  125. new(ps);
  126. if assigned(tsetconstnode(p).value_set) then
  127. ps^:=tsetconstnode(p).value_set^
  128. else
  129. ps^:=[];
  130. hp:=cconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  131. end;
  132. pointerconstn :
  133. begin
  134. hp:=cconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  135. end;
  136. niln :
  137. begin
  138. hp:=cconstsym.create_ord(orgname,constnil,0,p.resultdef);
  139. end;
  140. typen :
  141. begin
  142. if is_interface(p.resultdef) then
  143. begin
  144. if assigned(tobjectdef(p.resultdef).iidguid) then
  145. begin
  146. new(pg);
  147. pg^:=tobjectdef(p.resultdef).iidguid^;
  148. hp:=cconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  149. end
  150. else
  151. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  152. end
  153. else
  154. Message(parser_e_illegal_expression);
  155. end;
  156. inlinen:
  157. begin
  158. { this situation only happens if a intrinsic is parsed that has a
  159. generic type as its argument. As we don't know certain
  160. information about the final type yet, we need to use safe
  161. values (mostly 0, except for (Bit)SizeOf()) }
  162. if not parse_generic then
  163. Message(parser_e_illegal_expression);
  164. case tinlinenode(p).inlinenumber of
  165. in_sizeof_x:
  166. begin
  167. hp:=cconstsym.create_ord(orgname,constord,1,p.resultdef);
  168. end;
  169. in_bitsizeof_x:
  170. begin
  171. hp:=cconstsym.create_ord(orgname,constord,8,p.resultdef);
  172. end;
  173. { add other cases here if necessary }
  174. else
  175. Message(parser_e_illegal_expression);
  176. end;
  177. end;
  178. else
  179. begin
  180. { the node is from a generic parameter constant and is
  181. untyped so we need to pass a placeholder constant
  182. instead of givng an error }
  183. if nf_generic_para in p.flags then
  184. hp:=cconstsym.create_ord(orgname,constnil,0,p.resultdef)
  185. else
  186. Message(parser_e_illegal_expression);
  187. end;
  188. end;
  189. { transfer generic param flag from node to symbol }
  190. if nf_generic_para in p.flags then
  191. begin
  192. include(hp.symoptions,sp_generic_const);
  193. include(hp.symoptions,sp_generic_para);
  194. end;
  195. current_tokenpos:=storetokenpos;
  196. p.free;
  197. readconstant:=hp;
  198. end;
  199. procedure const_dec(out had_generic:boolean);
  200. begin
  201. consume(_CONST);
  202. consts_dec(false,true,had_generic);
  203. end;
  204. procedure consts_dec(in_structure, allow_typed_const: boolean;out had_generic:boolean);
  205. var
  206. orgname : TIDString;
  207. hdef : tdef;
  208. sym : tsym;
  209. flags : thccflags;
  210. dummysymoptions : tsymoptions;
  211. deprecatedmsg : pshortstring;
  212. storetokenpos,filepos : tfileposinfo;
  213. nodetype : tnodetype;
  214. old_block_type : tblock_type;
  215. first,
  216. isgeneric,
  217. expect_directive,
  218. skip_initialiser : boolean;
  219. varspez : tvarspez;
  220. asmtype : tasmlisttype;
  221. begin
  222. old_block_type:=block_type;
  223. block_type:=bt_const;
  224. had_generic:=false;
  225. first:=true;
  226. repeat
  227. orgname:=orgpattern;
  228. filepos:=current_tokenpos;
  229. isgeneric:=not (m_delphi in current_settings.modeswitches) and (token=_ID) and (idtoken=_GENERIC);
  230. consume(_ID);
  231. case token of
  232. _EQ:
  233. begin
  234. consume(_EQ);
  235. sym:=readconstant(orgname,filepos,nodetype);
  236. { Support hint directives }
  237. dummysymoptions:=[];
  238. deprecatedmsg:=nil;
  239. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  240. if assigned(sym) then
  241. begin
  242. sym.symoptions:=sym.symoptions+dummysymoptions;
  243. sym.deprecatedmsg:=deprecatedmsg;
  244. sym.visibility:=symtablestack.top.currentvisibility;
  245. symtablestack.top.insertsym(sym);
  246. sym.register_sym;
  247. {$ifdef jvm}
  248. { for the JVM target, some constants need to be
  249. initialized at run time (enums, sets) -> create fake
  250. typed const to do so (at least if they are visible
  251. outside this routine, since we won't directly access
  252. these symbols in the generated code) }
  253. if (symtablestack.top.symtablelevel<normal_function_level) and
  254. assigned(tconstsym(sym).constdef) and
  255. (tconstsym(sym).constdef.typ in [enumdef,setdef]) then
  256. jvm_add_typed_const_initializer(tconstsym(sym));
  257. {$endif}
  258. end
  259. else
  260. stringdispose(deprecatedmsg);
  261. consume(_SEMICOLON);
  262. end;
  263. _COLON:
  264. begin
  265. if not allow_typed_const then
  266. begin
  267. Message(parser_e_no_typed_const);
  268. consume_all_until(_SEMICOLON);
  269. end;
  270. { set the blocktype first so a consume also supports a
  271. caret, to support const s : ^string = nil }
  272. block_type:=bt_const_type;
  273. consume(_COLON);
  274. read_anon_type(hdef,false);
  275. block_type:=bt_const;
  276. { create symbol }
  277. storetokenpos:=current_tokenpos;
  278. current_tokenpos:=filepos;
  279. if not (cs_typed_const_writable in current_settings.localswitches) then
  280. begin
  281. varspez:=vs_const;
  282. asmtype:=al_rotypedconsts;
  283. end
  284. else
  285. begin
  286. varspez:=vs_value;
  287. asmtype:=al_typedconsts;
  288. end;
  289. { if we are dealing with structure const then we need to handle it as a
  290. structure static variable: create a symbol in unit symtable and a reference
  291. to it from the structure or linking will fail }
  292. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  293. begin
  294. { note: we keep hdef so that we might at least read the
  295. constant data correctly for error recovery }
  296. check_allowed_for_var_or_const(hdef,false);
  297. sym:=cfieldvarsym.create(orgname,varspez,hdef,[]);
  298. symtablestack.top.insertsym(sym);
  299. sym:=make_field_static(symtablestack.top,tfieldvarsym(sym));
  300. end
  301. else
  302. begin
  303. sym:=cstaticvarsym.create(orgname,varspez,hdef,[]);
  304. sym.visibility:=symtablestack.top.currentvisibility;
  305. symtablestack.top.insertsym(sym);
  306. end;
  307. sym.register_sym;
  308. current_tokenpos:=storetokenpos;
  309. skip_initialiser:=false;
  310. { Anonymous proctype definitions can have proc directives }
  311. if (
  312. (hdef.typ=procvardef) or
  313. is_funcref(hdef)
  314. ) and
  315. (hdef.typesym=nil) then
  316. begin
  317. { Either "procedure; stdcall" or "procedure stdcall" }
  318. expect_directive:=try_to_consume(_SEMICOLON);
  319. if check_proc_directive(true) then
  320. parse_proctype_directives(hdef)
  321. else if expect_directive then
  322. begin
  323. Message(parser_e_proc_directive_expected);
  324. skip_initialiser:=true;
  325. end;
  326. { add default calling convention }
  327. if hdef.typ=procvardef then
  328. flags:=hcc_default_actions_intf
  329. else
  330. flags:=hcc_default_actions_intf_struct;
  331. handle_calling_convention(hdef,flags);
  332. end;
  333. { Parse the initialiser }
  334. if not skip_initialiser then
  335. begin
  336. consume(_EQ);
  337. maybe_guarantee_record_typesym(tstaticvarsym(sym).vardef,tstaticvarsym(sym).vardef.owner);
  338. read_typed_const(current_asmdata.asmlists[asmtype],tstaticvarsym(sym),in_structure);
  339. end;
  340. end;
  341. else
  342. if not first and isgeneric and (token in [_PROCEDURE,_FUNCTION,_CLASS]) then
  343. begin
  344. had_generic:=true;
  345. break;
  346. end
  347. else
  348. { generate an error }
  349. consume(_EQ);
  350. end;
  351. first:=false;
  352. until (token<>_ID) or
  353. (in_structure and
  354. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  355. ((m_final_fields in current_settings.modeswitches) and
  356. (idtoken=_FINAL))));
  357. block_type:=old_block_type;
  358. end;
  359. procedure label_dec;
  360. var
  361. labelsym : tlabelsym;
  362. begin
  363. consume(_LABEL);
  364. if not(cs_support_goto in current_settings.moduleswitches) then
  365. Message(sym_e_goto_and_label_not_supported);
  366. repeat
  367. if not(token in [_ID,_INTCONST]) then
  368. consume(_ID)
  369. else
  370. begin
  371. if token=_ID then
  372. labelsym:=clabelsym.create(orgpattern)
  373. else
  374. begin
  375. { strip leading 0's in iso mode }
  376. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  377. while (length(pattern)>1) and (pattern[1]='0') do
  378. delete(pattern,1,1);
  379. labelsym:=clabelsym.create(pattern);
  380. end;
  381. symtablestack.top.insertsym(labelsym);
  382. if m_non_local_goto in current_settings.modeswitches then
  383. begin
  384. if symtablestack.top.symtabletype=localsymtable then
  385. begin
  386. labelsym.jumpbuf:=clocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  387. symtablestack.top.insertsym(labelsym.jumpbuf);
  388. end
  389. else
  390. begin
  391. labelsym.jumpbuf:=cstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  392. symtablestack.top.insertsym(labelsym.jumpbuf);
  393. cnodeutils.insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  394. end;
  395. include(labelsym.jumpbuf.symoptions,sp_internal);
  396. { the buffer will be setup later, but avoid a hint }
  397. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  398. end;
  399. consume(token);
  400. end;
  401. if token<>_SEMICOLON then consume(_COMMA);
  402. until not(token in [_ID,_INTCONST]);
  403. consume(_SEMICOLON);
  404. end;
  405. function find_create_constructor(objdef:tobjectdef):tsymentry;
  406. begin
  407. while assigned(objdef) do
  408. begin
  409. result:=objdef.symtable.Find('CREATE');
  410. if assigned(result) then
  411. exit;
  412. objdef:=objdef.childof;
  413. end;
  414. // A class without a constructor called 'create'?!?
  415. internalerror(2012111101);
  416. end;
  417. procedure parse_rttiattributes(var rtti_attrs_def:trtti_attribute_list);
  418. function read_attr_paras:tnode;
  419. var
  420. old_block_type : tblock_type;
  421. begin
  422. if try_to_consume(_LKLAMMER) then
  423. begin
  424. { we only want constants here }
  425. old_block_type:=block_type;
  426. block_type:=bt_const;
  427. result:=parse_paras(false,false,_RKLAMMER);
  428. block_type:=old_block_type;
  429. consume(_RKLAMMER);
  430. end
  431. else
  432. result:=nil;
  433. end;
  434. var
  435. p,paran,pcalln,ptmp : tnode;
  436. ecnt : longint;
  437. i,pcount : sizeint;
  438. paras : array of tnode;
  439. od : tobjectdef;
  440. constrsym : tsymentry;
  441. typesym : ttypesym;
  442. parasok : boolean;
  443. begin
  444. consume(_LECKKLAMMER);
  445. repeat
  446. { Parse attribute type }
  447. p:=factor(false,[ef_type_only,ef_check_attr_suffix]);
  448. if p.nodetype=typen then
  449. begin
  450. typesym:=ttypesym(ttypenode(p).typesym);
  451. od:=tobjectdef(ttypenode(p).typedef);
  452. { Check if the attribute class is related to TCustomAttribute }
  453. if not is_system_custom_attribute_descendant(od) then
  454. begin
  455. incompatibletypes(od,class_tcustomattribute);
  456. read_attr_paras.free;
  457. continue;
  458. end;
  459. paran:=read_attr_paras;
  460. { Search the tprocdef of the constructor which has to be called. }
  461. constrsym:=find_create_constructor(od);
  462. if constrsym.typ<>procsym then
  463. internalerror(2018102301);
  464. pcalln:=ccallnode.create(paran,tprocsym(constrsym),od.symtable,cloadvmtaddrnode.create(p),[cnf_no_convert_procvar],nil);
  465. p:=nil;
  466. ecnt:=errorcount;
  467. typecheckpass(pcalln);
  468. if (pcalln.nodetype=calln) and assigned(tcallnode(pcalln).procdefinition) and not codegenerror then
  469. begin
  470. { TODO: once extended RTTI for methods is supported, reject a
  471. constructor if it doesn't have extended RTTI enabled }
  472. { collect the parameters of the call node as there might be
  473. compile time type conversions (e.g. a Byte parameter being
  474. passed a value > 255) }
  475. paran:=tcallnode(pcalln).left;
  476. { only count visible parameters (thankfully open arrays are not
  477. supported, otherwise we'd need to handle those as well) }
  478. parasok:=true;
  479. paras:=nil;
  480. if assigned(paran) then
  481. begin
  482. ptmp:=paran;
  483. pcount:=0;
  484. while assigned(ptmp) do
  485. begin
  486. if not (vo_is_hidden_para in tcallparanode(ptmp).parasym.varoptions) then
  487. inc(pcount);
  488. ptmp:=tcallparanode(ptmp).right;
  489. end;
  490. setlength(paras,pcount);
  491. ptmp:=paran;
  492. pcount:=0;
  493. while assigned(ptmp) do
  494. begin
  495. if not (vo_is_hidden_para in tcallparanode(ptmp).parasym.varoptions) then
  496. begin
  497. if not is_constnode(tcallparanode(ptmp).left) then
  498. begin
  499. parasok:=false;
  500. messagepos(tcallparanode(ptmp).left.fileinfo,type_e_constant_expr_expected);
  501. end;
  502. paras[high(paras)-pcount]:=tcallparanode(ptmp).left.getcopy;
  503. inc(pcount);
  504. end;
  505. ptmp:=tcallparanode(ptmp).right;
  506. end;
  507. end;
  508. if parasok then
  509. begin
  510. { Add attribute to attribute list which will be added
  511. to the property which is defined next. }
  512. if not assigned(rtti_attrs_def) then
  513. rtti_attrs_def:=trtti_attribute_list.create;
  514. rtti_attrs_def.addattribute(typesym,tcallnode(pcalln).procdefinition,pcalln,paras);
  515. end
  516. else
  517. begin
  518. { cleanup }
  519. pcalln.free;
  520. for i:=0 to high(paras) do
  521. paras[i].free;
  522. end;
  523. end
  524. else begin
  525. { provide *some* error in case there hasn't been one }
  526. if errorcount=ecnt then
  527. message(parser_e_illegal_expression);
  528. pcalln.free;
  529. end;
  530. end
  531. else
  532. begin
  533. Message(type_e_type_id_expected);
  534. { try to recover by nevertheless reading the parameters (if any) }
  535. read_attr_paras.free;
  536. end;
  537. p.free;
  538. until not try_to_consume(_COMMA);
  539. consume(_RECKKLAMMER);
  540. end;
  541. function parse_forward_declaration(sym:tsym;gentypename,genorgtypename:tidstring;genericdef:tdef;generictypelist:tfphashobjectlist;out newtype:ttypesym):tdef;
  542. var
  543. wasforward : boolean;
  544. objecttype : tobjecttyp;
  545. gendef : tstoreddef;
  546. begin
  547. newtype:=nil;
  548. wasforward:=false;
  549. if ((token=_CLASS) or
  550. (token=_INTERFACE) or
  551. (token=_DISPINTERFACE) or
  552. (token=_OBJCCLASS) or
  553. (token=_OBJCPROTOCOL) or
  554. (token=_OBJCCATEGORY)) and
  555. (assigned(ttypesym(sym).typedef)) and
  556. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  557. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  558. begin
  559. wasforward:=true;
  560. objecttype:=odt_none;
  561. case token of
  562. _CLASS :
  563. objecttype:=default_class_type;
  564. _INTERFACE :
  565. case current_settings.interfacetype of
  566. it_interfacecom:
  567. objecttype:=odt_interfacecom;
  568. it_interfacecorba:
  569. objecttype:=odt_interfacecorba;
  570. it_interfacejava:
  571. objecttype:=odt_interfacejava;
  572. end;
  573. _DISPINTERFACE :
  574. objecttype:=odt_dispinterface;
  575. _OBJCCLASS,
  576. _OBJCCATEGORY :
  577. objecttype:=odt_objcclass;
  578. _OBJCPROTOCOL :
  579. objecttype:=odt_objcprotocol;
  580. else
  581. internalerror(200811072);
  582. end;
  583. consume(token);
  584. if assigned(genericdef) then
  585. gendef:=tstoreddef(genericdef)
  586. else
  587. { determine the generic def in case we are in a nested type
  588. of a specialization }
  589. gendef:=determine_generic_def(gentypename);
  590. { we can ignore the result, the definition is modified }
  591. object_dec(objecttype,genorgtypename,newtype,gendef,generictypelist,tobjectdef(ttypesym(sym).typedef),ht_none);
  592. if wasforward and
  593. (tobjectdef(ttypesym(sym).typedef).objecttype<>objecttype) then
  594. Message1(type_e_forward_interface_type_does_not_match,tobjectdef(ttypesym(sym).typedef).GetTypeName);
  595. newtype:=ttypesym(sym);
  596. result:=newtype.typedef;
  597. end
  598. else
  599. begin
  600. message1(parser_h_type_redef,genorgtypename);
  601. result:=generrordef;
  602. end;
  603. end;
  604. { From http://clang.llvm.org/docs/LanguageExtensions.html#objective-c-features :
  605. To determine whether a method has an inferred related result type, the first word in the camel-case selector
  606. (e.g., “init” in “initWithObjects”) is considered, and the method will have a related result type if its return
  607. type is compatible with the type of its class and if:
  608. * the first word is "alloc" or "new", and the method is a class method, or
  609. * the first word is "autorelease", "init", "retain", or "self", and the method is an instance method.
  610. If a method with a related result type is overridden by a subclass method, the subclass method must also return
  611. a type that is compatible with the subclass type.
  612. }
  613. procedure pd_set_objc_related_result(def: tobject; para: pointer);
  614. var
  615. pd: tprocdef;
  616. i, firstcamelend: longint;
  617. inferresult: boolean;
  618. begin
  619. if tdef(def).typ<>procdef then
  620. exit;
  621. pd:=tprocdef(def);
  622. if not(po_msgstr in pd.procoptions) then
  623. internalerror(2019082401);
  624. firstcamelend:=length(pd.messageinf.str^);
  625. for i:=1 to length(pd.messageinf.str^) do
  626. if pd.messageinf.str^[i] in ['A'..'Z'] then
  627. begin
  628. firstcamelend:=pred(i);
  629. break;
  630. end;
  631. case copy(pd.messageinf.str^,1,firstcamelend) of
  632. 'alloc',
  633. 'new':
  634. inferresult:=po_classmethod in pd.procoptions;
  635. 'autorelease',
  636. 'init',
  637. 'retain',
  638. 'self':
  639. inferresult:=not(po_classmethod in pd.procoptions);
  640. else
  641. inferresult:=false;
  642. end;
  643. if inferresult and
  644. def_is_related(tdef(pd.procsym.owner.defowner),pd.returndef) then
  645. include(pd.procoptions,po_objc_related_result_type);
  646. end;
  647. procedure types_dec(in_structure: boolean;out had_generic:boolean;var rtti_attrs_def: trtti_attribute_list);
  648. procedure finalize_class_external_status(od: tobjectdef);
  649. begin
  650. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  651. begin
  652. { formal definition: x = objcclass external; }
  653. exclude(od.objectoptions,oo_is_forward);
  654. include(od.objectoptions,oo_is_formal);
  655. end;
  656. end;
  657. var
  658. typename,orgtypename,
  659. gentypename,genorgtypename : TIDString;
  660. newtype : ttypesym;
  661. dummysym,
  662. sym : tsym;
  663. hdef,
  664. hdef2 : tdef;
  665. defpos,storetokenpos : tfileposinfo;
  666. old_block_type : tblock_type;
  667. old_checkforwarddefs: TFPObjectList;
  668. flags : thccflags;
  669. setdummysym,
  670. first,
  671. isgeneric,
  672. isunique,
  673. istyperenaming : boolean;
  674. generictypelist : tfphashobjectlist;
  675. localgenerictokenbuf : tdynamicarray;
  676. p:tnode;
  677. gendef : tstoreddef;
  678. s : shortstring;
  679. i : longint;
  680. {$ifdef x86}
  681. segment_register: string;
  682. {$endif x86}
  683. begin
  684. old_block_type:=block_type;
  685. { save unit container of forward declarations -
  686. we can be inside nested class type block }
  687. old_checkforwarddefs:=current_module.checkforwarddefs;
  688. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  689. block_type:=bt_type;
  690. hdef:=nil;
  691. first:=true;
  692. had_generic:=false;
  693. storetokenpos:=Default(tfileposinfo);
  694. repeat
  695. defpos:=current_tokenpos;
  696. istyperenaming:=false;
  697. setdummysym:=false;
  698. generictypelist:=nil;
  699. localgenerictokenbuf:=nil;
  700. { class attribute definitions? }
  701. if m_prefixed_attributes in current_settings.modeswitches then
  702. while token=_LECKKLAMMER do
  703. parse_rttiattributes(rtti_attrs_def);
  704. { fpc generic declaration? }
  705. if first then
  706. had_generic:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  707. isgeneric:=had_generic;
  708. typename:=pattern;
  709. orgtypename:=orgpattern;
  710. consume(_ID);
  711. { delphi generic declaration? }
  712. if (m_delphi in current_settings.modeswitches) then
  713. isgeneric:=token=_LSHARPBRACKET;
  714. { Generic type declaration? }
  715. if isgeneric then
  716. begin
  717. if assigned(current_genericdef) then
  718. Message(parser_f_no_generic_inside_generic);
  719. consume(_LSHARPBRACKET);
  720. generictypelist:=parse_generic_parameters(true);
  721. consume(_RSHARPBRACKET);
  722. str(generictypelist.Count,s);
  723. gentypename:=typename+'$'+s;
  724. genorgtypename:=orgtypename+'$'+s;
  725. end
  726. else
  727. begin
  728. gentypename:=typename;
  729. genorgtypename:=orgtypename;
  730. end;
  731. consume(_EQ);
  732. { support 'ttype=type word' syntax }
  733. isunique:=try_to_consume(_TYPE);
  734. { MacPas object model is more like Delphi's than like TP's, but }
  735. { uses the object keyword instead of class }
  736. if (m_mac in current_settings.modeswitches) and
  737. (token = _OBJECT) then
  738. token := _CLASS;
  739. { Start recording a generic template }
  740. if assigned(generictypelist) then
  741. begin
  742. localgenerictokenbuf:=tdynamicarray.create(256);
  743. current_scanner.startrecordtokens(localgenerictokenbuf);
  744. end;
  745. { is the type already defined? -- must be in the current symtable,
  746. not in a nested symtable or one higher up the stack -> don't
  747. use searchsym & friends! }
  748. sym:=tsym(symtablestack.top.find(gentypename));
  749. newtype:=nil;
  750. { found a symbol with this name? }
  751. if assigned(sym) then
  752. begin
  753. if (sym.typ=typesym) and
  754. { this should not be a symbol that was created by a generic
  755. that was declared earlier }
  756. not (
  757. (ttypesym(sym).typedef.typ=undefineddef) and
  758. (sp_generic_dummy in sym.symoptions)
  759. ) then
  760. begin
  761. hdef:=parse_forward_declaration(sym,gentypename,genorgtypename,nil,generictypelist,newtype);
  762. end;
  763. end;
  764. { no old type reused ? Then insert this new type }
  765. if not assigned(newtype) then
  766. begin
  767. if isgeneric then
  768. begin
  769. { we are not freeing the type parameters, so register them }
  770. for i:=0 to generictypelist.count-1 do
  771. begin
  772. tstoredsym(generictypelist[i]).register_sym;
  773. if tstoredsym(generictypelist[i]).typ=typesym then
  774. tstoreddef(ttypesym(generictypelist[i]).typedef).register_def;
  775. end;
  776. end;
  777. { insert the new type first with an errordef, so that
  778. referencing the type before it's really set it
  779. will give an error (PFV) }
  780. hdef:=generrordef;
  781. gendef:=nil;
  782. storetokenpos:=current_tokenpos;
  783. if isgeneric then
  784. begin
  785. { for generics we need to check whether a non-generic type
  786. already exists and if not we need to insert a symbol with
  787. the non-generic name (available in (org)typename) that is a
  788. undefineddef, so that inline specializations can be used }
  789. sym:=tsym(symtablestack.top.Find(typename));
  790. if not assigned(sym) then
  791. begin
  792. sym:=ctypesym.create(orgtypename,cundefineddef.create(true));
  793. Include(sym.symoptions,sp_generic_dummy);
  794. ttypesym(sym).typedef.typesym:=sym;
  795. sym.visibility:=symtablestack.top.currentvisibility;
  796. symtablestack.top.insertsym(sym);
  797. ttypesym(sym).typedef.owner:=sym.owner;
  798. end
  799. else
  800. { this is not allowed in non-Delphi modes }
  801. if not (m_delphi in current_settings.modeswitches) then
  802. Message1(sym_e_duplicate_id,genorgtypename)
  803. else
  804. begin
  805. { we need to find this symbol even if it's a variable or
  806. something else when doing an inline specialization }
  807. Include(sym.symoptions,sp_generic_dummy);
  808. add_generic_dummysym(sym);
  809. end;
  810. end
  811. else
  812. begin
  813. if assigned(sym) and (sym.typ=typesym) and
  814. (ttypesym(sym).typedef.typ=undefineddef) and
  815. (sp_generic_dummy in sym.symoptions) then
  816. begin
  817. { this is a symbol that was added by an earlier generic
  818. declaration, reuse it }
  819. newtype:=ttypesym(sym);
  820. newtype.typedef:=hdef;
  821. { use the correct casing }
  822. newtype.RealName:=genorgtypename;
  823. sym:=nil;
  824. end;
  825. { determine the generic def in case we are in a nested type
  826. of a specialization }
  827. gendef:=determine_generic_def(gentypename);
  828. end;
  829. { insert a new type if we don't reuse an existing symbol }
  830. if not assigned(newtype) then
  831. begin
  832. newtype:=ctypesym.create(genorgtypename,hdef);
  833. newtype.visibility:=symtablestack.top.currentvisibility;
  834. symtablestack.top.insertsym(newtype);
  835. end;
  836. current_tokenpos:=defpos;
  837. current_tokenpos:=storetokenpos;
  838. { read the type definition }
  839. read_named_type(hdef,newtype,gendef,generictypelist,false,isunique);
  840. { update the definition of the type }
  841. if assigned(hdef) then
  842. begin
  843. if assigned(hdef.typesym) then
  844. begin
  845. istyperenaming:=true;
  846. include(newtype.symoptions,sp_explicitrename);
  847. end;
  848. if isunique then
  849. begin
  850. if is_objc_class_or_protocol(hdef) or
  851. is_java_class_or_interface(hdef) then
  852. Message(parser_e_unique_unsupported);
  853. if is_object(hdef) or
  854. is_class_or_interface_or_dispinterface(hdef) then
  855. begin
  856. { just create a copy that is a child of the original class class type; this is
  857. Delphi-compatible }
  858. hdef2:=tstoreddef(hdef).getcopy;
  859. tobjectdef(hdef2).childof:=tobjectdef(hdef);
  860. tstoreddef(hdef2).orgdef:=tstoreddef(hdef);
  861. hdef:=hdef2;
  862. end
  863. else
  864. begin
  865. hdef2:=tstoreddef(hdef).getcopy;
  866. tstoreddef(hdef2).orgdef:=tstoreddef(hdef);
  867. hdef:=hdef2;
  868. { check if it is an ansistring(codepage) declaration }
  869. if is_ansistring(hdef) and try_to_consume(_LKLAMMER) then
  870. begin
  871. p:=comp_expr([ef_accept_equal]);
  872. consume(_RKLAMMER);
  873. if not is_constintnode(p) then
  874. begin
  875. Message(parser_e_illegal_expression);
  876. { error recovery }
  877. end
  878. else
  879. begin
  880. if (tordconstnode(p).value<0) or (tordconstnode(p).value>65535) then
  881. begin
  882. Message(parser_e_invalid_codepage);
  883. tordconstnode(p).value:=0;
  884. end;
  885. tstringdef(hdef).encoding:=int64(tordconstnode(p).value);
  886. end;
  887. p.free;
  888. end;
  889. if (hdef.typ in [pointerdef,classrefdef]) and
  890. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  891. current_module.checkforwarddefs.add(hdef);
  892. end;
  893. include(hdef.defoptions,df_unique);
  894. end;
  895. if not assigned(hdef.typesym) then
  896. begin
  897. hdef.typesym:=newtype;
  898. if sp_generic_dummy in newtype.symoptions then
  899. add_generic_dummysym(newtype);
  900. end;
  901. end;
  902. { in non-Delphi modes we need a reference to the generic def
  903. without the generic suffix, so it can be found easily when
  904. parsing method implementations }
  905. if isgeneric and assigned(sym) and
  906. not (m_delphi in current_settings.modeswitches) and
  907. (ttypesym(sym).typedef.typ=undefineddef) then
  908. begin
  909. { don't free the undefineddef as the defids rely on the count
  910. of the defs in the def list of the module}
  911. ttypesym(sym).typedef:=hdef;
  912. setdummysym:=true;
  913. end;
  914. newtype.typedef:=hdef;
  915. { ensure that the type is registered when no specialization is
  916. currently done }
  917. if (current_scanner.replay_stack_depth=0) and
  918. (
  919. (hdef.typ<>procvardef) or
  920. not (po_is_function_ref in tabstractprocdef(hdef).procoptions)
  921. ) then
  922. hdef.register_def;
  923. { KAZ: handle TGUID declaration in system unit }
  924. if (cs_compilesystem in current_settings.moduleswitches) and
  925. assigned(hdef) and
  926. (hdef.typ=recorddef) then
  927. begin
  928. if not assigned(rec_tguid) and
  929. (gentypename='TGUID') and
  930. (hdef.size=16) then
  931. rec_tguid:=trecorddef(hdef)
  932. else if not assigned(rec_jmp_buf) and
  933. (gentypename='JMP_BUF') then
  934. rec_jmp_buf:=trecorddef(hdef)
  935. else if not assigned(rec_exceptaddr) and
  936. (gentypename='TEXCEPTADDR') then
  937. rec_exceptaddr:=trecorddef(hdef);
  938. end;
  939. end;
  940. if assigned(hdef) then
  941. begin
  942. case hdef.typ of
  943. pointerdef :
  944. begin
  945. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  946. consume(_SEMICOLON);
  947. {$ifdef x86}
  948. {$ifdef i8086}
  949. if try_to_consume(_HUGE) then
  950. begin
  951. tcpupointerdef(hdef).x86pointertyp:=x86pt_huge;
  952. consume(_SEMICOLON);
  953. end
  954. else
  955. {$endif i8086}
  956. if try_to_consume(_FAR) then
  957. begin
  958. {$if defined(i8086)}
  959. tcpupointerdef(hdef).x86pointertyp:=x86pt_far;
  960. {$elseif defined(i386)}
  961. tcpupointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  962. {$elseif defined(x86_64)}
  963. { for compatibility with previous versions of fpc,
  964. far pointer = regular pointer on x86_64 }
  965. Message1(parser_w_ptr_type_ignored,'FAR');
  966. {$endif}
  967. consume(_SEMICOLON);
  968. end
  969. else
  970. if try_to_consume(_NEAR) then
  971. begin
  972. if token <> _SEMICOLON then
  973. begin
  974. segment_register:=get_stringconst;
  975. case UpCase(segment_register) of
  976. 'CS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_cs;
  977. 'DS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_ds;
  978. 'SS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_ss;
  979. 'ES': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_es;
  980. 'FS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_fs;
  981. 'GS': tcpupointerdef(hdef).x86pointertyp:=x86pt_near_gs;
  982. else
  983. Message(asmr_e_invalid_register);
  984. end;
  985. end
  986. else
  987. tcpupointerdef(hdef).x86pointertyp:=x86pt_near;
  988. consume(_SEMICOLON);
  989. end;
  990. {$else x86}
  991. { Previous versions of FPC support declaring a pointer as
  992. far even on non-x86 platforms. }
  993. if try_to_consume(_FAR) then
  994. begin
  995. Message1(parser_w_ptr_type_ignored,'FAR');
  996. consume(_SEMICOLON);
  997. end;
  998. {$endif x86}
  999. end;
  1000. procvardef :
  1001. begin
  1002. { in case of type renaming, don't parse proc directives }
  1003. if istyperenaming then
  1004. begin
  1005. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  1006. consume(_SEMICOLON);
  1007. end
  1008. else
  1009. begin
  1010. if not check_proc_directive(true) then
  1011. begin
  1012. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  1013. consume(_SEMICOLON);
  1014. end;
  1015. parse_proctype_directives(tprocvardef(hdef));
  1016. if po_is_function_ref in tprocvardef(hdef).procoptions then
  1017. begin
  1018. if not (m_function_references in current_settings.modeswitches) and
  1019. not (po_is_block in tprocvardef(hdef).procoptions) then
  1020. messagepos(storetokenpos,sym_e_error_in_type_def)
  1021. else
  1022. begin
  1023. if setdummysym then
  1024. dummysym:=sym
  1025. else
  1026. dummysym:=nil;
  1027. adjust_funcref(hdef,newtype,dummysym);
  1028. end;
  1029. if current_scanner.replay_stack_depth=0 then
  1030. hdef.register_def;
  1031. end;
  1032. if hdef.typ=procvardef then
  1033. flags:=hcc_default_actions_intf
  1034. else
  1035. flags:=hcc_default_actions_intf_struct;
  1036. handle_calling_convention(hdef,flags);
  1037. if (hdef.typ=procvardef) and (po_is_function_ref in tprocvardef(hdef).procoptions) then
  1038. begin
  1039. if (po_is_block in tprocvardef(hdef).procoptions) and
  1040. not (tprocvardef(hdef).proccalloption in [pocall_cdecl,pocall_mwpascal]) then
  1041. message(type_e_cblock_callconv);
  1042. end;
  1043. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  1044. consume(_SEMICOLON);
  1045. end;
  1046. end;
  1047. objectdef :
  1048. begin
  1049. if is_funcref(hdef) then
  1050. begin
  1051. if not check_proc_directive(true) then
  1052. begin
  1053. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  1054. consume(_SEMICOLON);
  1055. end;
  1056. parse_proctype_directives(hdef);
  1057. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  1058. consume(_SEMICOLON);
  1059. end
  1060. else
  1061. begin
  1062. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  1063. consume(_SEMICOLON);
  1064. end;
  1065. { change a forward and external class declaration into
  1066. formal external definition, so the compiler does not
  1067. expect an real definition later }
  1068. if is_objc_class_or_protocol(hdef) or
  1069. is_java_class_or_interface(hdef) then
  1070. finalize_class_external_status(tobjectdef(hdef));
  1071. { Build VMT indexes, skip for type renaming and forward classes }
  1072. if not istyperenaming and
  1073. not(oo_is_forward in tobjectdef(hdef).objectoptions) then
  1074. build_vmt(tobjectdef(hdef));
  1075. { In case of an objcclass, verify that all methods have a message
  1076. name set. We only check this now, because message names can be set
  1077. during the protocol (interface) mapping. At the same time, set the
  1078. mangled names (these depend on the "external" name of the class),
  1079. and mark private fields of external classes as "used" (to avoid
  1080. bogus notes about them being unused)
  1081. }
  1082. { watch out for crashes in case of errors }
  1083. if is_objc_class_or_protocol(hdef) and
  1084. (not is_objccategory(hdef) or
  1085. assigned(tobjectdef(hdef).childof)) then
  1086. begin
  1087. tobjectdef(hdef).finish_objc_data;
  1088. tobjectdef(hdef).symtable.DefList.ForEachCall(@pd_set_objc_related_result,nil);
  1089. end;
  1090. if is_cppclass(hdef) then
  1091. tobjectdef(hdef).finish_cpp_data;
  1092. end;
  1093. recorddef :
  1094. begin
  1095. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  1096. consume(_SEMICOLON);
  1097. end;
  1098. else
  1099. begin
  1100. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  1101. consume(_SEMICOLON);
  1102. end;
  1103. end;
  1104. { if we have a real type definition or a unique type we may bind
  1105. attributes to this def }
  1106. if not istyperenaming or isunique then
  1107. trtti_attribute_list.bind(rtti_attrs_def,tstoreddef(hdef).rtti_attribute_list);
  1108. if df_generic in hdef.defoptions then
  1109. { flag parent symtables that they now contain a generic }
  1110. hdef.owner.includeoption(sto_has_generic);
  1111. end;
  1112. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  1113. or is_objectpascal_helper(hdef)) then
  1114. begin
  1115. newtype.typedef:=generrordef;
  1116. message(parser_e_cant_create_generics_of_this_type);
  1117. end;
  1118. { Stop recording a generic template }
  1119. if assigned(generictypelist) then
  1120. begin
  1121. current_scanner.stoprecordtokens;
  1122. tstoreddef(hdef).generictokenbuf:=localgenerictokenbuf;
  1123. { Generic is never a type renaming }
  1124. hdef.typesym:=newtype;
  1125. { reusing a forward declared type also reuses the type parameters,
  1126. so free them if they haven't been used }
  1127. for i:=0 to generictypelist.count-1 do
  1128. begin
  1129. if (tstoredsym(generictypelist[i]).typ=typesym) and
  1130. not ttypesym(generictypelist[i]).typedef.is_registered then
  1131. ttypesym(generictypelist[i]).typedef.free;
  1132. if not tstoredsym(generictypelist[i]).is_registered then
  1133. tstoredsym(generictypelist[i]).free;
  1134. end;
  1135. generictypelist.free;
  1136. end;
  1137. if not (m_delphi in current_settings.modeswitches) and
  1138. (token=_ID) and (idtoken=_GENERIC) then
  1139. begin
  1140. had_generic:=true;
  1141. consume(_ID);
  1142. if token in [_PROCEDURE,_FUNCTION,_CLASS] then
  1143. break;
  1144. end
  1145. else
  1146. had_generic:=false;
  1147. first:=false;
  1148. if assigned(rtti_attrs_def) and (rtti_attrs_def.get_attribute_count>0) then
  1149. Message1(parser_e_unbound_attribute,trtti_attribute(rtti_attrs_def.rtti_attributes[0]).typesym.prettyname);
  1150. {$ifdef DEBUG_NODE_XML}
  1151. if Assigned(hdef) then
  1152. hdef.XMLPrintDef(newtype);
  1153. {$endif DEBUG_NODE_XML}
  1154. until ((token<>_ID) and (token<>_LECKKLAMMER)) or
  1155. (in_structure and
  1156. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  1157. ((m_final_fields in current_settings.modeswitches) and
  1158. (idtoken=_FINAL))));
  1159. { resolve type block forward declarations and restore a unit
  1160. container for them }
  1161. resolve_forward_types;
  1162. current_module.checkforwarddefs.free;
  1163. current_module.checkforwarddefs:=old_checkforwarddefs;
  1164. block_type:=old_block_type;
  1165. end;
  1166. { reads a type declaration to the symbol table }
  1167. procedure type_dec(out had_generic:boolean);
  1168. var
  1169. rtti_attrs_def: trtti_attribute_list;
  1170. begin
  1171. consume(_TYPE);
  1172. rtti_attrs_def := nil;
  1173. types_dec(false,had_generic,rtti_attrs_def);
  1174. rtti_attrs_def.free;
  1175. end;
  1176. procedure var_dec(out had_generic:boolean);
  1177. { parses variable declarations and inserts them in }
  1178. { the top symbol table of symtablestack }
  1179. begin
  1180. consume(_VAR);
  1181. read_var_decls([vd_check_generic],had_generic);
  1182. end;
  1183. procedure property_dec;
  1184. { parses a global property (fpc mode feature) }
  1185. var
  1186. old_block_type: tblock_type;
  1187. begin
  1188. consume(_PROPERTY);
  1189. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  1190. message(parser_e_property_only_sgr);
  1191. old_block_type:=block_type;
  1192. block_type:=bt_const;
  1193. repeat
  1194. read_property_dec(false, nil);
  1195. consume(_SEMICOLON);
  1196. until token<>_ID;
  1197. block_type:=old_block_type;
  1198. end;
  1199. procedure threadvar_dec(out had_generic:boolean);
  1200. { parses thread variable declarations and inserts them in }
  1201. { the top symbol table of symtablestack }
  1202. begin
  1203. consume(_THREADVAR);
  1204. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  1205. message(parser_e_threadvars_only_sg);
  1206. if f_threading in features then
  1207. read_var_decls([vd_threadvar,vd_check_generic],had_generic)
  1208. else
  1209. begin
  1210. Message1(parser_f_unsupported_feature,featurestr[f_threading]);
  1211. read_var_decls([vd_check_generic],had_generic);
  1212. end;
  1213. end;
  1214. procedure resourcestring_dec(out had_generic:boolean);
  1215. var
  1216. orgname : TIDString;
  1217. p : tnode;
  1218. dummysymoptions : tsymoptions;
  1219. deprecatedmsg : pshortstring;
  1220. storetokenpos,filepos : tfileposinfo;
  1221. old_block_type : tblock_type;
  1222. sp : pchar;
  1223. sym : tsym;
  1224. first,
  1225. isgeneric : boolean;
  1226. pw : pcompilerwidestring;
  1227. begin
  1228. if target_info.system in systems_managed_vm then
  1229. message(parser_e_feature_unsupported_for_vm);
  1230. consume(_RESOURCESTRING);
  1231. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  1232. message(parser_e_resourcestring_only_sg);
  1233. first:=true;
  1234. had_generic:=false;
  1235. old_block_type:=block_type;
  1236. block_type:=bt_const;
  1237. repeat
  1238. orgname:=orgpattern;
  1239. filepos:=current_tokenpos;
  1240. isgeneric:=not (m_delphi in current_settings.modeswitches) and (token=_ID) and (idtoken=_GENERIC);
  1241. consume(_ID);
  1242. case token of
  1243. _EQ:
  1244. begin
  1245. consume(_EQ);
  1246. p:=comp_expr([ef_accept_equal]);
  1247. storetokenpos:=current_tokenpos;
  1248. current_tokenpos:=filepos;
  1249. sym:=nil;
  1250. case p.nodetype of
  1251. ordconstn:
  1252. begin
  1253. if is_constcharnode(p) then
  1254. begin
  1255. getmem(sp,2);
  1256. sp[0]:=chr(tordconstnode(p).value.svalue);
  1257. sp[1]:=#0;
  1258. sym:=cconstsym.create_string(orgname,constresourcestring,sp,1,nil);
  1259. end
  1260. else
  1261. Message(parser_e_illegal_expression);
  1262. end;
  1263. stringconstn:
  1264. with Tstringconstnode(p) do
  1265. begin
  1266. if not is_systemunit_unicode then
  1267. begin
  1268. if cst_type in [cst_widestring,cst_unicodestring] then
  1269. changestringtype(getansistringdef);
  1270. getmem(sp,len+1);
  1271. move(value_str^,sp^,len+1);
  1272. sym:=cconstsym.create_string(orgname,constresourcestring,sp,len,nil);
  1273. end
  1274. else
  1275. begin
  1276. // For unicode rtl, resourcestrings are unicodestrings
  1277. if cst_type in [cst_conststring,cst_longstring, cst_shortstring,cst_ansistring] then
  1278. changestringtype(cunicodestringtype);
  1279. initwidestring(pw);
  1280. copywidestring(pcompilerwidestring(value_str),pw);
  1281. sym:=cconstsym.create_wstring(orgname,constwresourcestring,pw);
  1282. end;
  1283. end;
  1284. else
  1285. Message(parser_e_illegal_expression);
  1286. end;
  1287. current_tokenpos:=storetokenpos;
  1288. { Support hint directives }
  1289. dummysymoptions:=[];
  1290. deprecatedmsg:=nil;
  1291. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  1292. if assigned(sym) then
  1293. begin
  1294. sym.symoptions:=sym.symoptions+dummysymoptions;
  1295. sym.deprecatedmsg:=deprecatedmsg;
  1296. symtablestack.top.insertsym(sym);
  1297. end
  1298. else
  1299. stringdispose(deprecatedmsg);
  1300. consume(_SEMICOLON);
  1301. p.free;
  1302. end;
  1303. else
  1304. if not first and isgeneric and
  1305. (token in [_PROCEDURE, _FUNCTION, _CLASS]) then
  1306. begin
  1307. had_generic:=true;
  1308. break;
  1309. end
  1310. else
  1311. consume(_EQ);
  1312. end;
  1313. first:=false;
  1314. until token<>_ID;
  1315. block_type:=old_block_type;
  1316. end;
  1317. end.