pdecl.pas 58 KB

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