pdecl.pas 55 KB

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