pdecl.pas 56 KB

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