pdecl.pas 59 KB

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