pdecl.pas 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  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):tconstsym;
  30. procedure const_dec;
  31. procedure consts_dec(in_structure, allow_typed_const: boolean);
  32. procedure label_dec;
  33. procedure type_dec;
  34. procedure types_dec(in_structure: boolean);
  35. procedure var_dec;
  36. procedure threadvar_dec;
  37. procedure property_dec;
  38. procedure resourcestring_dec;
  39. procedure parse_rttiattributes(var rtti_attributes: trtti_attributesdef);
  40. procedure add_synthetic_rtti_funtion_declarations(rtti_attributesdef: trtti_attributesdef; name: shortstring);
  41. implementation
  42. uses
  43. SysUtils,
  44. { common }
  45. cutils,
  46. { global }
  47. globals,tokens,verbose,widestr,constexp,
  48. systems,
  49. { aasm }
  50. aasmbase,aasmtai,aasmdata,fmodule,
  51. { symtable }
  52. symconst,symbase,symtype,symtable,symcreat,paramgr,defutil,
  53. { pass 1 }
  54. htypechk,
  55. nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nobj,nmem,
  56. { codegen }
  57. ncgutil,ngenutil,
  58. { parser }
  59. scanner,
  60. pbase,pexpr,ptype,ptconst,pdecsub,pdecvar,pdecobj,pgenutil,
  61. {$ifdef jvm}
  62. pjvm,
  63. {$endif}
  64. { cpu-information }
  65. cpuinfo
  66. ;
  67. var
  68. current_rtticlassattributesdef : trtti_attributesdef;
  69. function readconstant(const orgname:string;const filepos:tfileposinfo):tconstsym;
  70. var
  71. hp : tconstsym;
  72. p : tnode;
  73. ps : pconstset;
  74. pd : pbestreal;
  75. pg : pguid;
  76. sp : pchar;
  77. pw : pcompilerwidestring;
  78. storetokenpos : tfileposinfo;
  79. begin
  80. readconstant:=nil;
  81. if orgname='' then
  82. internalerror(9584582);
  83. hp:=nil;
  84. p:=comp_expr(true,false);
  85. storetokenpos:=current_tokenpos;
  86. current_tokenpos:=filepos;
  87. case p.nodetype of
  88. ordconstn:
  89. begin
  90. if p.resultdef.typ=pointerdef then
  91. hp:=tconstsym.create_ordptr(orgname,constpointer,tordconstnode(p).value.uvalue,p.resultdef)
  92. else
  93. hp:=tconstsym.create_ord(orgname,constord,tordconstnode(p).value,p.resultdef);
  94. end;
  95. stringconstn:
  96. begin
  97. if is_wide_or_unicode_string(p.resultdef) then
  98. begin
  99. initwidestring(pw);
  100. copywidestring(pcompilerwidestring(tstringconstnode(p).value_str),pw);
  101. hp:=tconstsym.create_wstring(orgname,constwstring,pw);
  102. end
  103. else
  104. begin
  105. getmem(sp,tstringconstnode(p).len+1);
  106. move(tstringconstnode(p).value_str^,sp^,tstringconstnode(p).len+1);
  107. hp:=tconstsym.create_string(orgname,conststring,sp,tstringconstnode(p).len);
  108. end;
  109. end;
  110. realconstn :
  111. begin
  112. new(pd);
  113. pd^:=trealconstnode(p).value_real;
  114. hp:=tconstsym.create_ptr(orgname,constreal,pd,p.resultdef);
  115. end;
  116. setconstn :
  117. begin
  118. new(ps);
  119. ps^:=tsetconstnode(p).value_set^;
  120. hp:=tconstsym.create_ptr(orgname,constset,ps,p.resultdef);
  121. end;
  122. pointerconstn :
  123. begin
  124. hp:=tconstsym.create_ordptr(orgname,constpointer,tpointerconstnode(p).value,p.resultdef);
  125. end;
  126. niln :
  127. begin
  128. hp:=tconstsym.create_ord(orgname,constnil,0,p.resultdef);
  129. end;
  130. typen :
  131. begin
  132. if is_interface(p.resultdef) then
  133. begin
  134. if assigned(tobjectdef(p.resultdef).iidguid) then
  135. begin
  136. new(pg);
  137. pg^:=tobjectdef(p.resultdef).iidguid^;
  138. hp:=tconstsym.create_ptr(orgname,constguid,pg,p.resultdef);
  139. end
  140. else
  141. Message1(parser_e_interface_has_no_guid,tobjectdef(p.resultdef).objrealname^);
  142. end
  143. else
  144. Message(parser_e_illegal_expression);
  145. end;
  146. inlinen:
  147. begin
  148. { this situation only happens if a intrinsic is parsed that has a
  149. generic type as its argument. As we don't know certain
  150. information about the final type yet, we need to use safe
  151. values (mostly 0) }
  152. if not parse_generic then
  153. Message(parser_e_illegal_expression);
  154. case tinlinenode(p).inlinenumber of
  155. in_sizeof_x,
  156. in_bitsizeof_x:
  157. begin
  158. hp:=tconstsym.create_ord(orgname,constord,0,p.resultdef);
  159. end;
  160. { add other cases here if necessary }
  161. else
  162. Message(parser_e_illegal_expression);
  163. end;
  164. end;
  165. else
  166. Message(parser_e_illegal_expression);
  167. end;
  168. current_tokenpos:=storetokenpos;
  169. p.free;
  170. readconstant:=hp;
  171. end;
  172. procedure const_dec;
  173. begin
  174. consume(_CONST);
  175. consts_dec(false,true);
  176. end;
  177. procedure consts_dec(in_structure, allow_typed_const: boolean);
  178. var
  179. orgname : TIDString;
  180. hdef : tdef;
  181. sym : tsym;
  182. dummysymoptions : tsymoptions;
  183. deprecatedmsg : pshortstring;
  184. storetokenpos,filepos : tfileposinfo;
  185. old_block_type : tblock_type;
  186. skipequal : boolean;
  187. tclist : tasmlist;
  188. varspez : tvarspez;
  189. begin
  190. old_block_type:=block_type;
  191. block_type:=bt_const;
  192. repeat
  193. orgname:=orgpattern;
  194. filepos:=current_tokenpos;
  195. consume(_ID);
  196. case token of
  197. _EQ:
  198. begin
  199. consume(_EQ);
  200. sym:=readconstant(orgname,filepos);
  201. { Support hint directives }
  202. dummysymoptions:=[];
  203. deprecatedmsg:=nil;
  204. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  205. if assigned(sym) then
  206. begin
  207. sym.symoptions:=sym.symoptions+dummysymoptions;
  208. sym.deprecatedmsg:=deprecatedmsg;
  209. sym.visibility:=symtablestack.top.currentvisibility;
  210. symtablestack.top.insert(sym);
  211. {$ifdef jvm}
  212. { for the JVM target, some constants need to be
  213. initialized at run time (enums, sets) -> create fake
  214. typed const to do so }
  215. if assigned(tconstsym(sym).constdef) and
  216. (tconstsym(sym).constdef.typ in [enumdef,setdef]) then
  217. jvm_add_typed_const_initializer(tconstsym(sym));
  218. {$endif}
  219. end
  220. else
  221. stringdispose(deprecatedmsg);
  222. consume(_SEMICOLON);
  223. end;
  224. _COLON:
  225. begin
  226. if not allow_typed_const then
  227. begin
  228. Message(parser_e_no_typed_const);
  229. consume_all_until(_SEMICOLON);
  230. end;
  231. { set the blocktype first so a consume also supports a
  232. caret, to support const s : ^string = nil }
  233. block_type:=bt_const_type;
  234. consume(_COLON);
  235. read_anon_type(hdef,false);
  236. block_type:=bt_const;
  237. skipequal:=false;
  238. { create symbol }
  239. storetokenpos:=current_tokenpos;
  240. current_tokenpos:=filepos;
  241. if not (cs_typed_const_writable in current_settings.localswitches) then
  242. varspez:=vs_const
  243. else
  244. varspez:=vs_value;
  245. { if we are dealing with structure const then we need to handle it as a
  246. structure static variable: create a symbol in unit symtable and a reference
  247. to it from the structure or linking will fail }
  248. if symtablestack.top.symtabletype in [recordsymtable,ObjectSymtable] then
  249. begin
  250. sym:=tfieldvarsym.create(orgname,varspez,hdef,[]);
  251. symtablestack.top.insert(sym);
  252. sym:=make_field_static(symtablestack.top,tfieldvarsym(sym));
  253. end
  254. else
  255. begin
  256. sym:=tstaticvarsym.create(orgname,varspez,hdef,[]);
  257. sym.visibility:=symtablestack.top.currentvisibility;
  258. symtablestack.top.insert(sym);
  259. end;
  260. current_tokenpos:=storetokenpos;
  261. { procvar can have proc directives, but not type references }
  262. if (hdef.typ=procvardef) and
  263. (hdef.typesym=nil) then
  264. begin
  265. { support p : procedure;stdcall=nil; }
  266. if try_to_consume(_SEMICOLON) then
  267. begin
  268. if check_proc_directive(true) then
  269. parse_var_proc_directives(sym)
  270. else
  271. begin
  272. Message(parser_e_proc_directive_expected);
  273. skipequal:=true;
  274. end;
  275. end
  276. else
  277. { support p : procedure stdcall=nil; }
  278. begin
  279. if check_proc_directive(true) then
  280. parse_var_proc_directives(sym);
  281. end;
  282. { add default calling convention }
  283. handle_calling_convention(tabstractprocdef(hdef));
  284. end;
  285. if not skipequal then
  286. begin
  287. { get init value }
  288. consume(_EQ);
  289. if (cs_typed_const_writable in current_settings.localswitches) then
  290. tclist:=current_asmdata.asmlists[al_typedconsts]
  291. else
  292. tclist:=current_asmdata.asmlists[al_rotypedconsts];
  293. read_typed_const(tclist,tstaticvarsym(sym),in_structure);
  294. end;
  295. end;
  296. else
  297. { generate an error }
  298. consume(_EQ);
  299. end;
  300. until (token<>_ID) or
  301. (in_structure and
  302. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  303. ((m_final_fields in current_settings.modeswitches) and
  304. (idtoken=_FINAL))));
  305. block_type:=old_block_type;
  306. end;
  307. procedure label_dec;
  308. var
  309. labelsym : tlabelsym;
  310. begin
  311. consume(_LABEL);
  312. if not(cs_support_goto in current_settings.moduleswitches) then
  313. Message(sym_e_goto_and_label_not_supported);
  314. repeat
  315. if not(token in [_ID,_INTCONST]) then
  316. consume(_ID)
  317. else
  318. begin
  319. if token=_ID then
  320. labelsym:=tlabelsym.create(orgpattern)
  321. else
  322. labelsym:=tlabelsym.create(pattern);
  323. symtablestack.top.insert(labelsym);
  324. if m_non_local_goto in current_settings.modeswitches then
  325. begin
  326. if symtablestack.top.symtabletype=localsymtable then
  327. begin
  328. labelsym.jumpbuf:=tlocalvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  329. symtablestack.top.insert(labelsym.jumpbuf);
  330. end
  331. else
  332. begin
  333. labelsym.jumpbuf:=tstaticvarsym.create('LABEL$_'+labelsym.name,vs_value,rec_jmp_buf,[]);
  334. symtablestack.top.insert(labelsym.jumpbuf);
  335. cnodeutils.insertbssdata(tstaticvarsym(labelsym.jumpbuf));
  336. end;
  337. include(labelsym.jumpbuf.symoptions,sp_internal);
  338. { the buffer will be setup later, but avoid a hint }
  339. tabstractvarsym(labelsym.jumpbuf).varstate:=vs_written;
  340. end;
  341. consume(token);
  342. end;
  343. if token<>_SEMICOLON then consume(_COMMA);
  344. until not(token in [_ID,_INTCONST]);
  345. consume(_SEMICOLON);
  346. end;
  347. function find_create_constructor(objdef: tobjectdef): tsymentry;
  348. begin
  349. while assigned(objdef) do
  350. begin
  351. result:=objdef.symtable.Find('CREATE');
  352. if assigned(result) then
  353. exit;
  354. objdef:=objdef.childof;
  355. end;
  356. // A class without a constructor called 'create'?!?
  357. internalerror(2012111101);
  358. end;
  359. procedure parse_rttiattributes(var rtti_attributes: trtti_attributesdef);
  360. var
  361. p, p1: tnode;
  362. paras: tnode;
  363. again: boolean;
  364. od: tobjectdef;
  365. classattrdef: tobjectdef;
  366. constrsym: tsymentry;
  367. constrpd: tprocdef;
  368. typesym: ttypesym;
  369. oldblock_type: tblock_type;
  370. begin
  371. consume(_LECKKLAMMER);
  372. { Parse attribute type }
  373. p := factor(false,true);
  374. if p.nodetype<>errorn then
  375. begin
  376. typesym := ttypesym(ttypenode(p).typesym);
  377. od := tobjectdef(ttypenode(p).typedef);
  378. classattrdef := tobjectdef(search_system_type('TCUSTOMATTRIBUTE').typedef);
  379. if not od.is_related(classattrdef) then
  380. incompatibletypes(od,classattrdef);
  381. { Search the tprocdef of the constructor which has to be called. }
  382. constrsym := find_create_constructor(od);
  383. if constrsym.typ<>procsym then
  384. internalerror(2012102301);
  385. constrpd:=tprocsym(constrsym).find_procdef_bytype(potype_constructor);
  386. { Parse the attribute-parameters as if it is a list of parameters from
  387. a call to the constrpd constructor in an execution-block. }
  388. p1 := cloadvmtaddrnode.create(ctypenode.create(od));
  389. again:=true;
  390. oldblock_type := block_type;
  391. block_type := bt_body;
  392. do_member_read(od,false,constrpd.procsym,p1,again,[]);
  393. block_type:=oldblock_type;
  394. { Add attribute to attribute list which will be added
  395. to the property which is defined next. }
  396. if not assigned(rtti_attributes) then
  397. rtti_attributes := trtti_attributesdef.create;
  398. rtti_attributes.addattribute(typesym,p1);
  399. Include(current_module.rtti_options, rmo_hasattributes);
  400. end;
  401. p.free;
  402. consume(_RECKKLAMMER);
  403. end;
  404. procedure add_synthetic_rtti_funtion_declarations(rtti_attributesdef: trtti_attributesdef; name: shortstring);
  405. var
  406. i: Integer;
  407. sstate: tscannerstate;
  408. attribute: trtti_attribute;
  409. pd: tprocdef;
  410. begin
  411. for i := 0 to rtti_attributesdef.get_attribute_count-1 do
  412. begin
  413. attribute := trtti_attribute(rtti_attributesdef.rtti_attributes[i]);
  414. replace_scanner('rtti_class_attributes',sstate);
  415. if str_parse_method_dec('function rtti_'+name+'_'+IntToStr(i)+':'+ attribute.typesym.Name +';',potype_function,false,tabstractrecorddef(ttypesym(attribute.typesym).typedef),pd) then
  416. pd.synthetickind:=tsk_get_rttiattribute
  417. else
  418. internalerror(2012052601);
  419. pd.skpara:=attribute;
  420. attribute.symbolname:=pd.mangledname;
  421. restore_scanner(sstate);
  422. end;
  423. end;
  424. procedure types_dec(in_structure: boolean);
  425. procedure finalize_class_external_status(od: tobjectdef);
  426. begin
  427. if [oo_is_external,oo_is_forward] <= od.objectoptions then
  428. begin
  429. { formal definition: x = objcclass external; }
  430. exclude(od.objectoptions,oo_is_forward);
  431. include(od.objectoptions,oo_is_formal);
  432. end;
  433. end;
  434. var
  435. typename,orgtypename,
  436. gentypename,genorgtypename : TIDString;
  437. newtype : ttypesym;
  438. sym : tsym;
  439. hdef : tdef;
  440. defpos,storetokenpos : tfileposinfo;
  441. old_block_type : tblock_type;
  442. old_checkforwarddefs: TFPObjectList;
  443. objecttype : tobjecttyp;
  444. isgeneric,
  445. isunique,
  446. istyperenaming : boolean;
  447. generictypelist : TFPObjectList;
  448. generictokenbuf : tdynamicarray;
  449. vmtbuilder : TVMTBuilder;
  450. p:tnode;
  451. gendef : tstoreddef;
  452. s : shortstring;
  453. pd: tprocdef;
  454. hashedid : thashedidstring;
  455. begin
  456. old_block_type:=block_type;
  457. { save unit container of forward declarations -
  458. we can be inside nested class type block }
  459. old_checkforwarddefs:=current_module.checkforwarddefs;
  460. current_module.checkforwarddefs:=TFPObjectList.Create(false);
  461. block_type:=bt_type;
  462. repeat
  463. defpos:=current_tokenpos;
  464. istyperenaming:=false;
  465. generictypelist:=nil;
  466. generictokenbuf:=nil;
  467. { class attribute definitions? }
  468. if m_prefixed_attributes in current_settings.modeswitches then
  469. while token=_LECKKLAMMER do
  470. begin
  471. parse_rttiattributes(current_rtticlassattributesdef);
  472. end;
  473. { fpc generic declaration? }
  474. isgeneric:=not(m_delphi in current_settings.modeswitches) and try_to_consume(_GENERIC);
  475. typename:=pattern;
  476. orgtypename:=orgpattern;
  477. consume(_ID);
  478. { delphi generic declaration? }
  479. if (m_delphi in current_settings.modeswitches) then
  480. isgeneric:=token=_LSHARPBRACKET;
  481. { Generic type declaration? }
  482. if isgeneric then
  483. begin
  484. if assigned(current_genericdef) then
  485. Message(parser_f_no_generic_inside_generic);
  486. consume(_LSHARPBRACKET);
  487. generictypelist:=parse_generic_parameters;
  488. consume(_RSHARPBRACKET);
  489. str(generictypelist.Count,s);
  490. gentypename:=typename+'$'+s;
  491. genorgtypename:=orgtypename+'$'+s;
  492. end
  493. else
  494. begin
  495. gentypename:=typename;
  496. genorgtypename:=orgtypename;
  497. end;
  498. consume(_EQ);
  499. { support 'ttype=type word' syntax }
  500. isunique:=try_to_consume(_TYPE);
  501. { MacPas object model is more like Delphi's than like TP's, but }
  502. { uses the object keyword instead of class }
  503. if (m_mac in current_settings.modeswitches) and
  504. (token = _OBJECT) then
  505. token := _CLASS;
  506. { Start recording a generic template }
  507. if assigned(generictypelist) then
  508. begin
  509. generictokenbuf:=tdynamicarray.create(256);
  510. current_scanner.startrecordtokens(generictokenbuf);
  511. end;
  512. { is the type already defined? -- must be in the current symtable,
  513. not in a nested symtable or one higher up the stack -> don't
  514. use searchsym & frinds! }
  515. sym:=tsym(symtablestack.top.find(gentypename));
  516. newtype:=nil;
  517. { found a symbol with this name? }
  518. if assigned(sym) then
  519. begin
  520. if (sym.typ=typesym) and
  521. { this should not be a symbol that was created by a generic
  522. that was declared earlier }
  523. not (
  524. (ttypesym(sym).typedef.typ=undefineddef) and
  525. (sp_generic_dummy in sym.symoptions)
  526. ) then
  527. begin
  528. if ((token=_CLASS) or
  529. (token=_INTERFACE) or
  530. (token=_DISPINTERFACE) or
  531. (token=_OBJCCLASS) or
  532. (token=_OBJCPROTOCOL) or
  533. (token=_OBJCCATEGORY)) and
  534. (assigned(ttypesym(sym).typedef)) and
  535. is_implicit_pointer_object_type(ttypesym(sym).typedef) and
  536. (oo_is_forward in tobjectdef(ttypesym(sym).typedef).objectoptions) then
  537. begin
  538. case token of
  539. _CLASS :
  540. objecttype:=default_class_type;
  541. _INTERFACE :
  542. case current_settings.interfacetype of
  543. it_interfacecom:
  544. objecttype:=odt_interfacecom;
  545. it_interfacecorba:
  546. objecttype:=odt_interfacecorba;
  547. it_interfacejava:
  548. objecttype:=odt_interfacejava;
  549. else
  550. internalerror(2010122611);
  551. end;
  552. _DISPINTERFACE :
  553. objecttype:=odt_dispinterface;
  554. _OBJCCLASS,
  555. _OBJCCATEGORY :
  556. objecttype:=odt_objcclass;
  557. _OBJCPROTOCOL :
  558. objecttype:=odt_objcprotocol;
  559. else
  560. internalerror(200811072);
  561. end;
  562. consume(token);
  563. { we can ignore the result, the definition is modified }
  564. object_dec(objecttype,genorgtypename,newtype,nil,nil,tobjectdef(ttypesym(sym).typedef),ht_none);
  565. newtype:=ttypesym(sym);
  566. hdef:=newtype.typedef;
  567. end
  568. else
  569. message1(parser_h_type_redef,genorgtypename);
  570. end;
  571. end;
  572. { no old type reused ? Then insert this new type }
  573. if not assigned(newtype) then
  574. begin
  575. { insert the new type first with an errordef, so that
  576. referencing the type before it's really set it
  577. will give an error (PFV) }
  578. hdef:=generrordef;
  579. gendef:=nil;
  580. storetokenpos:=current_tokenpos;
  581. if isgeneric then
  582. begin
  583. { for generics we need to check whether a non-generic type
  584. already exists and if not we need to insert a symbol with
  585. the non-generic name (available in (org)typename) that is a
  586. undefineddef, so that inline specializations can be used }
  587. sym:=tsym(symtablestack.top.Find(typename));
  588. if not assigned(sym) then
  589. begin
  590. sym:=ttypesym.create(orgtypename,tundefineddef.create);
  591. Include(sym.symoptions,sp_generic_dummy);
  592. ttypesym(sym).typedef.typesym:=sym;
  593. sym.visibility:=symtablestack.top.currentvisibility;
  594. symtablestack.top.insert(sym);
  595. ttypesym(sym).typedef.owner:=sym.owner;
  596. end
  597. else
  598. { this is not allowed in non-Delphi modes }
  599. if not (m_delphi in current_settings.modeswitches) then
  600. Message1(sym_e_duplicate_id,genorgtypename)
  601. else
  602. { we need to find this symbol even if it's a variable or
  603. something else when doing an inline specialization }
  604. Include(sym.symoptions,sp_generic_dummy);
  605. end
  606. else
  607. begin
  608. if assigned(sym) and (sym.typ=typesym) and
  609. (ttypesym(sym).typedef.typ=undefineddef) and
  610. (sp_generic_dummy in sym.symoptions) then
  611. begin
  612. { this is a symbol that was added by an earlier generic
  613. declaration, reuse it }
  614. newtype:=ttypesym(sym);
  615. newtype.typedef:=hdef;
  616. sym:=nil;
  617. end;
  618. { check whether this is a declaration of a type inside a
  619. specialization }
  620. if assigned(current_structdef) and
  621. (df_specialization in current_structdef.defoptions) then
  622. begin
  623. if not assigned(current_structdef.genericdef) or
  624. not (current_structdef.genericdef.typ in [recorddef,objectdef]) then
  625. internalerror(2011052301);
  626. hashedid.id:=gentypename;
  627. { we could be inside a method of the specialization
  628. instead of its declaration, so check that first (as
  629. local nested types aren't allowed we don't need to
  630. walk the symtablestack to find the localsymtable) }
  631. if symtablestack.top.symtabletype=localsymtable then
  632. begin
  633. { we are in a method }
  634. if not assigned(symtablestack.top.defowner) or
  635. (symtablestack.top.defowner.typ<>procdef) then
  636. internalerror(2011120701);
  637. pd:=tprocdef(symtablestack.top.defowner);
  638. if not assigned(pd.genericdef) or (pd.genericdef.typ<>procdef) then
  639. internalerror(2011120702);
  640. sym:=tsym(tprocdef(pd.genericdef).localst.findwithhash(hashedid));
  641. end
  642. else
  643. sym:=nil;
  644. if not assigned(sym) or not (sym.typ=typesym) then
  645. begin
  646. { now search in the declaration of the generic }
  647. sym:=tsym(tabstractrecorddef(current_structdef.genericdef).symtable.findwithhash(hashedid));
  648. if not assigned(sym) or not (sym.typ=typesym) then
  649. internalerror(2011052302);
  650. end;
  651. { use the corresponding type in the generic's symtable as
  652. genericdef for the specialized type }
  653. gendef:=tstoreddef(ttypesym(sym).typedef);
  654. end;
  655. end;
  656. { insert a new type if we don't reuse an existing symbol }
  657. if not assigned(newtype) then
  658. begin
  659. newtype:=ttypesym.create(genorgtypename,hdef);
  660. newtype.visibility:=symtablestack.top.currentvisibility;
  661. symtablestack.top.insert(newtype);
  662. end;
  663. current_tokenpos:=defpos;
  664. current_tokenpos:=storetokenpos;
  665. { read the type definition }
  666. read_named_type(hdef,newtype,gendef,generictypelist,false);
  667. { update the definition of the type }
  668. if assigned(hdef) then
  669. begin
  670. if assigned(hdef.typesym) then
  671. begin
  672. istyperenaming:=true;
  673. include(newtype.symoptions,sp_explicitrename);
  674. end;
  675. if isunique then
  676. begin
  677. if is_objc_class_or_protocol(hdef) or
  678. is_java_class_or_interface(hdef) then
  679. Message(parser_e_unique_unsupported);
  680. hdef:=tstoreddef(hdef).getcopy;
  681. { check if it is an ansistirng(codepage) declaration }
  682. if is_ansistring(hdef) and try_to_consume(_LKLAMMER) then
  683. begin
  684. p:=comp_expr(true,false);
  685. consume(_RKLAMMER);
  686. if not is_constintnode(p) then
  687. begin
  688. Message(parser_e_illegal_expression);
  689. { error recovery }
  690. end
  691. else
  692. begin
  693. if (tordconstnode(p).value<0) or (tordconstnode(p).value>65535) then
  694. begin
  695. Message(parser_e_invalid_codepage);
  696. tordconstnode(p).value:=0;
  697. end;
  698. tstringdef(hdef).encoding:=int64(tordconstnode(p).value);
  699. end;
  700. p.free;
  701. end;
  702. { fix name, it is used e.g. for tables }
  703. if is_class_or_interface_or_dispinterface(hdef) then
  704. with tobjectdef(hdef) do
  705. begin
  706. stringdispose(objname);
  707. stringdispose(objrealname);
  708. objrealname:=stringdup(genorgtypename);
  709. objname:=stringdup(upper(genorgtypename));
  710. end;
  711. include(hdef.defoptions,df_unique);
  712. if (hdef.typ in [pointerdef,classrefdef]) and
  713. (tabstractpointerdef(hdef).pointeddef.typ=forwarddef) then
  714. current_module.checkforwarddefs.add(hdef);
  715. end;
  716. if not assigned(hdef.typesym) then
  717. hdef.typesym:=newtype;
  718. end;
  719. { in non-Delphi modes we need a reference to the generic def
  720. without the generic suffix, so it can be found easily when
  721. parsing method implementations }
  722. if isgeneric and assigned(sym) and
  723. not (m_delphi in current_settings.modeswitches) and
  724. (ttypesym(sym).typedef.typ=undefineddef) then
  725. { don't free the undefineddef as the defids rely on the count
  726. of the defs in the def list of the module}
  727. ttypesym(sym).typedef:=hdef;
  728. newtype.typedef:=hdef;
  729. { KAZ: handle TGUID declaration in system unit }
  730. if (cs_compilesystem in current_settings.moduleswitches) and not assigned(rec_tguid) and
  731. (gentypename='TGUID') and { name: TGUID and size=16 bytes that is 128 bits }
  732. assigned(hdef) and (hdef.typ=recorddef) and (hdef.size=16) then
  733. rec_tguid:=trecorddef(hdef);
  734. end;
  735. if assigned(hdef) then
  736. begin
  737. case hdef.typ of
  738. pointerdef :
  739. begin
  740. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  741. consume(_SEMICOLON);
  742. if try_to_consume(_FAR) then
  743. begin
  744. tpointerdef(hdef).is_far:=true;
  745. consume(_SEMICOLON);
  746. end;
  747. end;
  748. procvardef :
  749. begin
  750. { in case of type renaming, don't parse proc directives }
  751. if istyperenaming then
  752. begin
  753. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  754. consume(_SEMICOLON);
  755. end
  756. else
  757. begin
  758. if not check_proc_directive(true) then
  759. begin
  760. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  761. consume(_SEMICOLON);
  762. end;
  763. parse_var_proc_directives(tsym(newtype));
  764. handle_calling_convention(tprocvardef(hdef));
  765. if try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg) then
  766. consume(_SEMICOLON);
  767. end;
  768. end;
  769. objectdef :
  770. begin
  771. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  772. consume(_SEMICOLON);
  773. { change a forward and external class declaration into
  774. formal external definition, so the compiler does not
  775. expect an real definition later }
  776. if is_objc_class_or_protocol(hdef) or
  777. is_java_class_or_interface(hdef) then
  778. finalize_class_external_status(tobjectdef(hdef));
  779. { Build VMT indexes, skip for type renaming and forward classes }
  780. if (hdef.typesym=newtype) and
  781. not(oo_is_forward in tobjectdef(hdef).objectoptions) and
  782. not(df_generic in hdef.defoptions) then
  783. begin
  784. vmtbuilder:=TVMTBuilder.Create(tobjectdef(hdef));
  785. vmtbuilder.generate_vmt;
  786. vmtbuilder.free;
  787. end;
  788. { If there are attribute-properties available, bind them to
  789. this object }
  790. if assigned(current_rtticlassattributesdef) then
  791. begin
  792. add_synthetic_rtti_funtion_declarations(current_rtticlassattributesdef,hdef.typesym.Name);
  793. tobjectdef(hdef).rtti_attributesdef:=current_rtticlassattributesdef;
  794. current_rtticlassattributesdef := nil;
  795. end;
  796. { In case of an objcclass, verify that all methods have a message
  797. name set. We only check this now, because message names can be set
  798. during the protocol (interface) mapping. At the same time, set the
  799. mangled names (these depend on the "external" name of the class),
  800. and mark private fields of external classes as "used" (to avoid
  801. bogus notes about them being unused)
  802. }
  803. { watch out for crashes in case of errors }
  804. if is_objc_class_or_protocol(hdef) and
  805. (not is_objccategory(hdef) or
  806. assigned(tobjectdef(hdef).childof)) then
  807. tobjectdef(hdef).finish_objc_data;
  808. if is_cppclass(hdef) then
  809. tobjectdef(hdef).finish_cpp_data;
  810. end;
  811. recorddef :
  812. begin
  813. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  814. consume(_SEMICOLON);
  815. end;
  816. else
  817. begin
  818. try_consume_hintdirective(newtype.symoptions,newtype.deprecatedmsg);
  819. consume(_SEMICOLON);
  820. end;
  821. end;
  822. end;
  823. if isgeneric and (not(hdef.typ in [objectdef,recorddef,arraydef,procvardef])
  824. or is_objectpascal_helper(hdef)) then
  825. message(parser_e_cant_create_generics_of_this_type);
  826. { Stop recording a generic template }
  827. if assigned(generictypelist) then
  828. begin
  829. current_scanner.stoprecordtokens;
  830. tstoreddef(hdef).generictokenbuf:=generictokenbuf;
  831. { Generic is never a type renaming }
  832. hdef.typesym:=newtype;
  833. generictypelist.free;
  834. end;
  835. if assigned(current_rtticlassattributesdef) and (current_rtticlassattributesdef.get_attribute_count>0) then
  836. Message1(scan_e_unresolved_attribute,trtti_attribute(current_rtticlassattributesdef.rtti_attributes[0]).typesym.prettyname);
  837. until ((token<>_ID) and (token<>_LECKKLAMMER)) or
  838. (in_structure and
  839. ((idtoken in [_PRIVATE,_PROTECTED,_PUBLIC,_PUBLISHED,_STRICT]) or
  840. ((m_final_fields in current_settings.modeswitches) and
  841. (idtoken=_FINAL))));
  842. { resolve type block forward declarations and restore a unit
  843. container for them }
  844. resolve_forward_types;
  845. current_module.checkforwarddefs.free;
  846. current_module.checkforwarddefs:=old_checkforwarddefs;
  847. block_type:=old_block_type;
  848. end;
  849. { reads a type declaration to the symbol table }
  850. procedure type_dec;
  851. begin
  852. consume(_TYPE);
  853. types_dec(false);
  854. end;
  855. procedure var_dec;
  856. { parses variable declarations and inserts them in }
  857. { the top symbol table of symtablestack }
  858. begin
  859. consume(_VAR);
  860. read_var_decls([]);
  861. end;
  862. procedure property_dec;
  863. { parses a global property (fpc mode feature) }
  864. var
  865. old_block_type: tblock_type;
  866. begin
  867. consume(_PROPERTY);
  868. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  869. message(parser_e_resourcestring_only_sg);
  870. old_block_type:=block_type;
  871. block_type:=bt_const;
  872. repeat
  873. read_property_dec(false, nil);
  874. consume(_SEMICOLON);
  875. until token<>_ID;
  876. block_type:=old_block_type;
  877. end;
  878. procedure threadvar_dec;
  879. { parses thread variable declarations and inserts them in }
  880. { the top symbol table of symtablestack }
  881. begin
  882. consume(_THREADVAR);
  883. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  884. message(parser_e_threadvars_only_sg);
  885. read_var_decls([vd_threadvar]);
  886. end;
  887. procedure resourcestring_dec;
  888. var
  889. orgname : TIDString;
  890. p : tnode;
  891. dummysymoptions : tsymoptions;
  892. deprecatedmsg : pshortstring;
  893. storetokenpos,filepos : tfileposinfo;
  894. old_block_type : tblock_type;
  895. sp : pchar;
  896. sym : tsym;
  897. begin
  898. if target_info.system in systems_managed_vm then
  899. message(parser_e_feature_unsupported_for_vm);
  900. consume(_RESOURCESTRING);
  901. if not(symtablestack.top.symtabletype in [staticsymtable,globalsymtable]) then
  902. message(parser_e_resourcestring_only_sg);
  903. old_block_type:=block_type;
  904. block_type:=bt_const;
  905. repeat
  906. orgname:=orgpattern;
  907. filepos:=current_tokenpos;
  908. consume(_ID);
  909. case token of
  910. _EQ:
  911. begin
  912. consume(_EQ);
  913. p:=comp_expr(true,false);
  914. storetokenpos:=current_tokenpos;
  915. current_tokenpos:=filepos;
  916. sym:=nil;
  917. case p.nodetype of
  918. ordconstn:
  919. begin
  920. if is_constcharnode(p) then
  921. begin
  922. getmem(sp,2);
  923. sp[0]:=chr(tordconstnode(p).value.svalue);
  924. sp[1]:=#0;
  925. sym:=tconstsym.create_string(orgname,constresourcestring,sp,1);
  926. end
  927. else
  928. Message(parser_e_illegal_expression);
  929. end;
  930. stringconstn:
  931. with Tstringconstnode(p) do
  932. begin
  933. getmem(sp,len+1);
  934. move(value_str^,sp^,len+1);
  935. sym:=tconstsym.create_string(orgname,constresourcestring,sp,len);
  936. end;
  937. else
  938. Message(parser_e_illegal_expression);
  939. end;
  940. current_tokenpos:=storetokenpos;
  941. { Support hint directives }
  942. dummysymoptions:=[];
  943. deprecatedmsg:=nil;
  944. try_consume_hintdirective(dummysymoptions,deprecatedmsg);
  945. if assigned(sym) then
  946. begin
  947. sym.symoptions:=sym.symoptions+dummysymoptions;
  948. sym.deprecatedmsg:=deprecatedmsg;
  949. symtablestack.top.insert(sym);
  950. end
  951. else
  952. stringdispose(deprecatedmsg);
  953. consume(_SEMICOLON);
  954. p.free;
  955. end;
  956. else consume(_EQ);
  957. end;
  958. until token<>_ID;
  959. block_type:=old_block_type;
  960. end;
  961. end.