pdecl.pas 54 KB

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