pdecl.pas 46 KB

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