2
0

pdecl.pas 55 KB

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