objcutil.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. {
  2. Copyright (c) 2009 by Jonas Maebe
  3. This unit implements some Objective-C helper routines at the node tree
  4. level.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$i fpcdefs.inc}
  19. unit objcutil;
  20. interface
  21. uses
  22. node,
  23. symtype,symdef;
  24. { Generate a node loading the superclass structure necessary to call
  25. an inherited Objective-C method. }
  26. function objcsuperclassnode(def: tobjectdef): tnode;
  27. { The internals of Objective-C's @encode() functionality: encode a
  28. type into the internal format used by the run time. Returns false
  29. if a type is not representable by the Objective-C run time, and in
  30. that case also the failing definition. }
  31. function objctryencodetype(def: tdef; out encodedtype: ansistring; out founderror: tdef): boolean;
  32. { Encode a method's parameters and result type into the format used by the
  33. run time (for generating protocol and class rtti). }
  34. function objcencodemethod(pd: tprocdef): ansistring;
  35. { Check whether a type can be used in an Objective-C method
  36. signature or field declaration. }
  37. function objcchecktype(def: tdef; out founderror: tdef): boolean;
  38. implementation
  39. uses
  40. globtype,
  41. cutils,cclasses,
  42. pass_1,
  43. verbose,
  44. symtable,symconst,symsym,
  45. defutil,paramgr,
  46. nbas,nmem,ncal,nld;
  47. {******************************************************************
  48. objcsuperclassnode
  49. *******************************************************************}
  50. function objcsuperclassnode(def: tobjectdef): tnode;
  51. var
  52. block: tnode;
  53. statements: tstatementnode;
  54. para: tcallparanode;
  55. begin
  56. { only valid for Objective-C classes }
  57. if not is_objcclass(def) then
  58. internalerror(2009032903);
  59. block:=internalstatements(statements);
  60. para:=ccallparanode.create(cloadvmtaddrnode.create(ctypenode.create(def)),nil);
  61. addstatement(statements,ccallnode.createinternfromunit('OBJC1','CLASS_GETSUPERCLASS',para));
  62. typecheckpass(block);
  63. result:=block;
  64. end;
  65. {******************************************************************
  66. Type encoding
  67. *******************************************************************}
  68. type
  69. trecordinfostate = (ris_initial, ris_afterpointer, ris_dontprint);
  70. function objcparasize(def: tdef; varspez: tvarspez): ptrint;
  71. begin
  72. if paramanager.push_addr_param(varspez,def,pocall_cdecl) then
  73. result:=sizeof(pint)
  74. else
  75. begin
  76. result:=def.size;
  77. { In Objective-C, all ordinal types are widened to at least
  78. the size of the C "int" type. Assume __LP64__/4 byte ints for now. }
  79. if is_ordinal(def) and
  80. (result<4) then
  81. result:=4;
  82. end;
  83. end;
  84. function addencodedtype(def: tdef; recordinfostate: trecordinfostate; bpacked: boolean; var encodedstr: ansistring; out founderror: tdef): boolean; forward;
  85. function encoderecst(const recname: ansistring; recst: tabstractrecordsymtable; var encodedstr: ansistring; out founderror: tdef): boolean;
  86. var
  87. variantstarts: tfplist;
  88. i, varindex: longint;
  89. field,
  90. firstfield: tfieldvarsym;
  91. firstfieldvariant,
  92. bpacked: boolean;
  93. begin
  94. result:=false;
  95. bpacked:=recst.fieldalignment=bit_alignment;
  96. { Is the first field already the start of a variant? }
  97. firstfield:=nil;
  98. firstfieldvariant:=false;
  99. for i:=0 to recst.symlist.count-1 do
  100. begin
  101. if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
  102. continue;
  103. field:=tfieldvarsym(recst.symlist[i]);
  104. if not assigned(firstfield) then
  105. firstfield:=field
  106. else if (vo_is_first_field in field.varoptions) then
  107. begin
  108. if (field.fieldoffset=firstfield.fieldoffset) then
  109. firstfieldvariant:=true;
  110. end;
  111. end;
  112. variantstarts:=tfplist.create;
  113. encodedstr:=encodedstr+'{'+recname+'=';
  114. for i:=0 to recst.symlist.count-1 do
  115. begin
  116. if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
  117. continue;
  118. field:=tfieldvarsym(recst.symlist[i]);
  119. { start of a variant part? }
  120. if ((field=firstfield) and
  121. firstfieldvariant) or
  122. ((field<>firstfield) and
  123. (vo_is_first_field in field.varoptions)) then
  124. begin
  125. varindex:=variantstarts.count-1;
  126. if (varindex=-1) or
  127. (tfieldvarsym(variantstarts[varindex]).fieldoffset<field.fieldoffset) then
  128. begin
  129. { new, more deeply nested variant }
  130. encodedstr:=encodedstr+'(?={?=';
  131. variantstarts.add(field);
  132. end
  133. else
  134. begin
  135. { close existing nested variants if any }
  136. while (varindex>=0) and
  137. (tfieldvarsym(variantstarts[varindex]).fieldoffset>field.fieldoffset) do
  138. begin
  139. { close more deeply nested variants }
  140. encodedstr:=encodedstr+'})';
  141. dec(varindex);
  142. end;
  143. if (varindex<0) then
  144. internalerror(2009081805);
  145. if (tfieldvarsym(variantstarts[varindex]).fieldoffset<>field.fieldoffset) then
  146. internalerror(2009081804);
  147. { variant at the same level as a previous one }
  148. variantstarts.count:=varindex+1;
  149. { No need to add this field, it has the same offset as the
  150. previous one at this position. }
  151. if tfieldvarsym(variantstarts[varindex]).fieldoffset<>field.fieldoffset then
  152. internalerror(2009081601);
  153. { close previous variant sub-part and start new one }
  154. encodedstr:=encodedstr+'}{?=';
  155. end
  156. end;
  157. if not addencodedtype(field.vardef,ris_afterpointer,bpacked,encodedstr,founderror) then
  158. exit;
  159. end;
  160. for i:=0 to variantstarts.count-1 do
  161. encodedstr:=encodedstr+'})';
  162. variantstarts.free;
  163. encodedstr:=encodedstr+'}';
  164. result:=true
  165. end;
  166. function addencodedtype(def: tdef; recordinfostate: trecordinfostate; bpacked: boolean; var encodedstr: ansistring; out founderror: tdef): boolean;
  167. var
  168. recname: ansistring;
  169. recdef: trecorddef;
  170. objdef: tobjectdef;
  171. len: aint;
  172. c: char;
  173. newstate: trecordinfostate;
  174. addrpara: boolean;
  175. begin
  176. result:=true;
  177. case def.typ of
  178. stringdef :
  179. begin
  180. case tstringdef(def).stringtype of
  181. st_shortstring:
  182. { include length byte }
  183. encodedstr:=encodedstr+'['+tostr(tstringdef(def).len+1)+'C]';
  184. else
  185. { While we could handle refcounted Pascal strings correctly
  186. when such methods are called from Pascal code, things would
  187. completely break down if they were called from Objective-C
  188. code/reflection since the necessary refcount helper calls
  189. would be missing on the caller side (unless we'd
  190. automatically generate wrappers). }
  191. result:=false;
  192. end;
  193. end;
  194. enumdef,
  195. orddef :
  196. begin
  197. if bpacked and
  198. not is_void(def) then
  199. encodedstr:=encodedstr+'b'+tostr(def.packedbitsize)
  200. else
  201. begin
  202. if is_void(def) then
  203. c:='v'
  204. { in gcc, sizeof(_Bool) = sizeof(char) }
  205. else if is_boolean(def) and
  206. (def.size=1) then
  207. c:='B'
  208. else
  209. begin
  210. case def.size of
  211. 1:
  212. c:='c';
  213. 2:
  214. c:='s';
  215. 4:
  216. c:='i';
  217. 8:
  218. c:='q';
  219. else
  220. internalerror(2009081502);
  221. end;
  222. if not is_signed(def) then
  223. c:=upcase(c);
  224. end;
  225. encodedstr:=encodedstr+c;
  226. end;
  227. end;
  228. pointerdef :
  229. begin
  230. if is_pchar(def) then
  231. encodedstr:=encodedstr+'*'
  232. else if (def=objc_idtype) then
  233. encodedstr:=encodedstr+'@'
  234. else if (def=objc_seltype) then
  235. encodedstr:=encodedstr+':'
  236. else if (def=objc_metaclasstype) then
  237. encodedstr:=encodedstr+'#'
  238. else
  239. begin
  240. encodedstr:=encodedstr+'^';
  241. newstate:=recordinfostate;
  242. if (recordinfostate<ris_dontprint) then
  243. newstate:=succ(newstate);
  244. if not addencodedtype(tpointerdef(def).pointeddef,newstate,false,encodedstr,founderror) then
  245. begin
  246. result:=false;
  247. { report the exact (nested) error defintion }
  248. exit;
  249. end;
  250. end;
  251. end;
  252. floatdef :
  253. begin
  254. case tfloatdef(def).floattype of
  255. s32real:
  256. c:='f';
  257. s64real:
  258. c:='d';
  259. else
  260. begin
  261. c:='!';
  262. result:=false;
  263. end;
  264. end;
  265. encodedstr:=encodedstr+c;
  266. end;
  267. filedef :
  268. result:=false;
  269. recorddef :
  270. begin
  271. if assigned(def.typesym) then
  272. recname:=def.typename
  273. else
  274. recname:='?';
  275. if (recordinfostate<>ris_dontprint) then
  276. begin
  277. if not encoderecst(recname,tabstractrecordsymtable(trecorddef(def).symtable),encodedstr,founderror) then
  278. begin
  279. result:=false;
  280. { report the exact (nested) error defintion }
  281. exit;
  282. end
  283. end
  284. else
  285. encodedstr:=encodedstr+'{'+recname+'}'
  286. end;
  287. variantdef :
  288. begin
  289. recdef:=trecorddef(search_system_type('TVARDATA').typedef);
  290. if (recordinfostate<>ris_dontprint) then
  291. begin
  292. if not encoderecst(recdef.typename,tabstractrecordsymtable(recdef.symtable),encodedstr,founderror) then
  293. begin
  294. result:=false;
  295. { report the exact (nested) error defintion }
  296. exit;
  297. end
  298. end
  299. else
  300. encodedstr:=encodedstr+'{'+recdef.typename+'}';
  301. end;
  302. classrefdef :
  303. begin
  304. encodedstr:=encodedstr+'^';
  305. newstate:=recordinfostate;
  306. if (recordinfostate<>ris_dontprint) then
  307. newstate:=succ(newstate);
  308. if is_objcclassref(def) then
  309. begin
  310. objdef:=tobjectdef(tclassrefdef(def).pointeddef);
  311. if (newstate<>ris_dontprint) then
  312. { anonymous (objc)class definitions do not exist }
  313. begin
  314. if not encoderecst(objdef.objextname^,tabstractrecordsymtable(objdef.symtable),encodedstr,founderror) then
  315. { The fields of an Objective-C class should always be
  316. encodeable. }
  317. internalerror(2009081702);
  318. end
  319. else
  320. encodedstr:=encodedstr+'{'+objdef.objextname^+'}'
  321. end
  322. { Object Pascal classrefdefs point to a vmt, not really useful
  323. to completely write those here. I'm not even sure what the
  324. Objective-C run time uses this information for, since in C you
  325. can have forward struct definitions so not all structs passed
  326. to functions can be written out here either -> treat
  327. classrefdefs the same as such forward-defined structs. }
  328. else
  329. begin
  330. if assigned(def.typesym) then
  331. recname:=def.typename
  332. else
  333. recname:='?';
  334. encodedstr:=encodedstr+'{'+recname;
  335. if (newstate<>ris_dontprint) then
  336. encodedstr:=encodedstr+'=';
  337. encodedstr:=encodedstr+'}'
  338. end;
  339. end;
  340. setdef :
  341. begin
  342. addrpara:=paramanager.push_addr_param(vs_value,def,pocall_cdecl);
  343. if not addrpara then
  344. { encode as an record, they are always passed by value in C. }
  345. encodedstr:=encodedstr+'{?=';
  346. { Encode the set itself as an array. Without an encompassing
  347. record, these are always passed by reference in C. }
  348. encodedstr:=encodedstr+'['+tostr(def.size)+'C]';
  349. if not addrpara then
  350. encodedstr:=encodedstr+'}';
  351. end;
  352. formaldef :
  353. begin
  354. encodedstr:=encodedstr+'^v';
  355. end;
  356. arraydef :
  357. begin
  358. if is_array_of_const(def) then
  359. { do nothing, varargs are ignored in signatures }
  360. else if is_special_array(def) then
  361. result:=false
  362. else
  363. begin
  364. len:=tarraydef(def).highrange-tarraydef(def).lowrange+1;
  365. if is_packed_array(def) then
  366. begin
  367. { convert from bits to bytes for bitpacked arrays }
  368. len:=(len+7) div 8;
  369. { and encode as plain array of bytes }
  370. encodedstr:=encodedstr+'['+tostr(len)+'C]';
  371. end
  372. else
  373. begin
  374. encodedstr:=encodedstr+'['+tostr(len);
  375. { Embedded structured types in the array are printed
  376. in full regardless of the current recordinfostate. }
  377. if not addencodedtype(tarraydef(def).elementdef,ris_initial,false,encodedstr,founderror) then
  378. begin
  379. result:=false;
  380. { report the exact (nested) error defintion }
  381. exit;
  382. end;
  383. encodedstr:=encodedstr+']';
  384. end;
  385. end;
  386. end;
  387. procvardef :
  388. encodedstr:=encodedstr+'^?';
  389. objectdef :
  390. case tobjectdef(def).objecttype of
  391. odt_class,
  392. odt_object,
  393. odt_cppclass:
  394. begin
  395. newstate:=recordinfostate;
  396. { implicit pointer for classes }
  397. if (tobjectdef(def).objecttype=odt_class) then
  398. begin
  399. encodedstr:=encodedstr+'^';
  400. if (recordinfostate<ris_dontprint) then
  401. newstate:=succ(newstate);
  402. end;
  403. if newstate<>ris_dontprint then
  404. begin
  405. if not encoderecst(def.typename,tabstractrecordsymtable(tobjectdef(def).symtable),encodedstr,founderror) then
  406. begin
  407. result:=false;
  408. { report the exact (nested) error defintion }
  409. exit;
  410. end
  411. end
  412. else
  413. encodedstr:=encodedstr+'{'+def.typename+'}'
  414. end;
  415. odt_interfacecom,
  416. odt_interfacecom_property,
  417. odt_interfacecom_function,
  418. odt_dispinterface:
  419. result:=false;
  420. odt_interfacecorba:
  421. encodedstr:=encodedstr+'^{'+def.typename+'=}';
  422. { In Objective-C, the actual types of class instances are
  423. NSObject* etc, and those are encoded as "@". In FPC, to keep
  424. the similarity with Delphi-style Object Pascal, the type is
  425. NSObject and the pointer is implicit. Objective-C's "NSObject"
  426. has "class of NSObject" as equivalent here. }
  427. odt_objcclass,
  428. odt_objcprotocol:
  429. encodedstr:=encodedstr+'@';
  430. else
  431. internalerror(2009081509);
  432. end;
  433. undefineddef,
  434. errordef :
  435. result:=false;
  436. procdef :
  437. { must be done via objcencodemethod() }
  438. internalerror(2009081511);
  439. else
  440. internalerror(2009150812);
  441. end;
  442. if not result then
  443. founderror:=def;
  444. end;
  445. function objctryencodetype(def: tdef; out encodedtype: ansistring; out founderror: tdef): boolean;
  446. begin
  447. result:=addencodedtype(def,ris_initial,false,encodedtype,founderror);
  448. end;
  449. function objcencodemethod(pd: tprocdef): ansistring;
  450. var
  451. parasize,
  452. totalsize: aint;
  453. vs: tparavarsym;
  454. i: longint;
  455. temp: ansistring;
  456. founderror: tdef;
  457. begin
  458. result:='';
  459. totalsize:=0;
  460. for i:=0 to pd.parast.symlist.count-1 do
  461. begin
  462. vs:=tparavarsym(pd.parast.symlist[i]);
  463. { addencodedtype always assumes a value/const parameter, so add
  464. a pointer indirection for var/out parameters. }
  465. if not paramanager.push_addr_param(vs_value,vs.vardef,pocall_cdecl) and
  466. (vs.varspez in [vs_var,vs_out]) then
  467. result:=result+'^';
  468. { Add the parameter type. }
  469. if not addencodedtype(vs.vardef,ris_initial,false,result,founderror) then
  470. { should be checked earlier on }
  471. internalerror(2009081701);
  472. { And the total size of the parameters coming before this one
  473. (i.e., the "offset" of this parameter). }
  474. result:=result+tostr(totalsize);
  475. { Update the total parameter size }
  476. parasize:=objcparasize(vs.vardef,vs.varspez);
  477. inc(totalsize,parasize);
  478. end;
  479. { Prepend the total parameter size. }
  480. result:=tostr(totalsize)+result;
  481. { And the type of the function result (void in case of a procedure). }
  482. temp:='';
  483. if not addencodedtype(pd.returndef,ris_initial,false,temp,founderror) then
  484. internalerror(2009081801);
  485. result:=temp+result;
  486. end;
  487. {******************************************************************
  488. ObjC type validity checking
  489. *******************************************************************}
  490. function objcdochecktype(def: tdef; recordinfostate: trecordinfostate; out founderror: tdef): boolean; forward;
  491. function checkrecsttype(recst: tabstractrecordsymtable; recordinfostate: trecordinfostate; out founderror: tdef): boolean;
  492. var
  493. i: longint;
  494. field: tfieldvarsym;
  495. newstate: trecordinfostate;
  496. begin
  497. result:=false;
  498. newstate:=recordinfostate;
  499. { Although we never have to print the type info for nested
  500. records, check them anyway in case we're not after a pointer
  501. since if such records contain refcounted types then they
  502. can cause just as much trouble as if they were a simple
  503. refcounted field. }
  504. if (newstate=ris_afterpointer) then
  505. newstate:=ris_dontprint;
  506. for i:=0 to recst.symlist.count-1 do
  507. begin
  508. if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
  509. continue;
  510. field:=tfieldvarsym(recst.symlist[i]);
  511. if not objcdochecktype(field.vardef,newstate,founderror) then
  512. exit;
  513. end;
  514. result:=true
  515. end;
  516. function objcdochecktype(def: tdef; recordinfostate: trecordinfostate; out founderror: tdef): boolean;
  517. var
  518. recdef: trecorddef;
  519. objdef: tobjectdef;
  520. newstate: trecordinfostate;
  521. begin
  522. result:=true;
  523. case def.typ of
  524. stringdef :
  525. begin
  526. case tstringdef(def).stringtype of
  527. st_shortstring:
  528. ;
  529. else
  530. { While we could handle refcounted Pascal strings correctly
  531. when such methods are called from Pascal code, things would
  532. completely break down if they were called from Objective-C
  533. code/reflection since the necessary refcount helper calls
  534. would be missing on the caller side (unless we'd
  535. automatically generate wrappers). }
  536. result:=false;
  537. end;
  538. end;
  539. enumdef,
  540. orddef :
  541. ;
  542. pointerdef :
  543. begin
  544. newstate:=recordinfostate;
  545. if (recordinfostate<ris_dontprint) then
  546. newstate:=succ(newstate);
  547. if not objcdochecktype(tpointerdef(def).pointeddef,newstate,founderror) then
  548. begin
  549. result:=false;
  550. { report the exact (nested) error defintion }
  551. exit;
  552. end;
  553. end;
  554. floatdef :
  555. begin
  556. case tfloatdef(def).floattype of
  557. s32real,
  558. s64real:
  559. ;
  560. else
  561. result:=false;
  562. end;
  563. end;
  564. filedef :
  565. result:=false;
  566. recorddef :
  567. begin
  568. if (recordinfostate<>ris_dontprint) then
  569. begin
  570. if not checkrecsttype(tabstractrecordsymtable(trecorddef(def).symtable),recordinfostate,founderror) then
  571. begin
  572. result:=false;
  573. { report the exact (nested) error defintion }
  574. exit;
  575. end
  576. end
  577. end;
  578. variantdef :
  579. begin
  580. recdef:=trecorddef(search_system_type('TVARDATA').typedef);
  581. if (recordinfostate<>ris_dontprint) then
  582. begin
  583. if not checkrecsttype(tabstractrecordsymtable(recdef.symtable),recordinfostate,founderror) then
  584. begin
  585. result:=false;
  586. { report the exact (nested) error defintion }
  587. exit;
  588. end
  589. end;
  590. end;
  591. classrefdef:
  592. begin
  593. if is_objcclassref(def) then
  594. begin
  595. objdef:=tobjectdef(tclassrefdef(def).pointeddef);
  596. newstate:=recordinfostate;
  597. if (recordinfostate<ris_dontprint) then
  598. newstate:=succ(newstate);
  599. if (newstate<>ris_dontprint) then
  600. begin
  601. if not checkrecsttype(tabstractrecordsymtable(objdef.symtable),recordinfostate,founderror) then
  602. begin
  603. result:=false;
  604. { report the exact (nested) error defintion }
  605. exit;
  606. end
  607. end
  608. end
  609. end;
  610. setdef,
  611. formaldef :
  612. ;
  613. arraydef :
  614. begin
  615. if is_array_of_const(def) then
  616. { ok, varargs are ignored in signatures }
  617. else if is_special_array(def) then
  618. result:=false
  619. else
  620. begin
  621. if not is_packed_array(def) then
  622. begin
  623. if not objcdochecktype(tarraydef(def).elementdef,ris_initial,founderror) then
  624. begin
  625. result:=false;
  626. { report the exact (nested) error defintion }
  627. exit;
  628. end;
  629. end;
  630. end;
  631. end;
  632. procvardef :
  633. ;
  634. objectdef :
  635. case tobjectdef(def).objecttype of
  636. odt_class,
  637. odt_object,
  638. odt_cppclass:
  639. begin
  640. newstate:=recordinfostate;
  641. { implicit pointer for classes }
  642. if (tobjectdef(def).objecttype=odt_class) then
  643. begin
  644. if (recordinfostate<ris_dontprint) then
  645. newstate:=succ(newstate);
  646. end;
  647. if newstate<>ris_dontprint then
  648. begin
  649. if not checkrecsttype(tabstractrecordsymtable(tobjectdef(def).symtable),newstate,founderror) then
  650. begin
  651. result:=false;
  652. { report the exact (nested) error defintion }
  653. exit;
  654. end
  655. end
  656. end;
  657. odt_interfacecom,
  658. odt_interfacecom_property,
  659. odt_interfacecom_function,
  660. odt_dispinterface:
  661. result:=false;
  662. odt_interfacecorba,
  663. odt_objcclass,
  664. odt_objcprotocol:
  665. ;
  666. else
  667. internalerror(2009081709);
  668. end;
  669. undefineddef,
  670. errordef :
  671. result:=false;
  672. procdef :
  673. result:=false;
  674. else
  675. internalerror(2009170812);
  676. end;
  677. if not result then
  678. founderror:=def;
  679. end;
  680. function objcchecktype(def: tdef; out founderror: tdef): boolean;
  681. begin
  682. result:=objcdochecktype(def,ris_initial,founderror);
  683. end;
  684. end.