pdecl.pas 54 KB

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