pdecl.pas 55 KB

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