objcutil.pas 28 KB

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