objcutil.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  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: tdef): 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,ncon;
  47. {******************************************************************
  48. objcsuperclassnode
  49. *******************************************************************}
  50. function objcsuperclassnode(def: tdef): tnode;
  51. var
  52. para: tcallparanode;
  53. begin
  54. { only valid for Objective-C classes and classrefs }
  55. if not is_objcclass(def) and
  56. not is_objcclassref(def) then
  57. internalerror(2009090901);
  58. { Can be done a lot more efficiently with direct symbol accesses, but
  59. requires extra node types. Maybe later. }
  60. if is_objcclassref(def) then
  61. begin
  62. para:=ccallparanode.create(cstringconstnode.createstr(tobjectdef(tclassrefdef(def).pointeddef).objextname^),nil);
  63. para:=ccallparanode.create(ccallnode.createinternfromunit('OBJC1','OBJC_GETMETACLASS',para),nil);
  64. end
  65. else
  66. para:=ccallparanode.create(cloadvmtaddrnode.create(ctypenode.create(def)),nil);
  67. result:=ccallnode.createinternfromunit('OBJC1','CLASS_GETSUPERCLASS',para);
  68. typecheckpass(result);
  69. end;
  70. {******************************************************************
  71. Type encoding
  72. *******************************************************************}
  73. type
  74. trecordinfostate = (ris_initial, ris_afterpointer, ris_dontprint);
  75. function objcparasize(vs: tparavarsym): ptrint;
  76. begin
  77. result:=vs.paraloc[callerside].intsize;
  78. { In Objective-C, all ordinal types are widened to at least the
  79. size of the C "int" type. Assume __LP64__/4 byte ints for now. }
  80. if is_ordinal(vs.vardef) and
  81. (result<4) then
  82. result:=4;
  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. if not pd.has_paraloc_info then
  461. begin
  462. pd.requiredargarea:=paramanager.create_paraloc_info(pd,callerside);
  463. pd.has_paraloc_info:=true;
  464. end;
  465. {$if defined(powerpc) and defined(dummy)}
  466. { Disabled, because neither Clang nor gcc does this, and the ObjC
  467. runtime contains an explicit fix to detect this error. }
  468. { On ppc, the callee is responsible for removing the hidden function
  469. result parameter from the stack, so it has to know. On i386, it's
  470. the caller that does this. }
  471. if (pd.returndef<>voidtype) and
  472. paramgr.ret_in_param(pd.returndef,pocall_cdecl) then
  473. inc(totalsize,sizeof(pint));
  474. {$endif}
  475. for i:=0 to pd.paras.count-1 do
  476. begin
  477. vs:=tparavarsym(pd.paras[i]);
  478. if (vo_is_funcret in vs.varoptions) then
  479. continue;
  480. { addencodedtype always assumes a value parameter, so add
  481. a pointer indirection for var/out parameters. }
  482. if not paramanager.push_addr_param(vs_value,vs.vardef,pocall_cdecl) and
  483. (vs.varspez in [vs_var,vs_out]) then
  484. result:=result+'^';
  485. { Add the parameter type. }
  486. if not addencodedtype(vs.vardef,ris_initial,false,result,founderror) then
  487. { should be checked earlier on }
  488. internalerror(2009081701);
  489. { And the total size of the parameters coming before this one
  490. (i.e., the "offset" of this parameter). }
  491. result:=result+tostr(totalsize);
  492. { Update the total parameter size }
  493. parasize:=objcparasize(vs);
  494. inc(totalsize,parasize);
  495. end;
  496. { Prepend the total parameter size. }
  497. result:=tostr(totalsize)+result;
  498. { And the type of the function result (void in case of a procedure). }
  499. temp:='';
  500. if not addencodedtype(pd.returndef,ris_initial,false,temp,founderror) then
  501. internalerror(2009081801);
  502. result:=temp+result;
  503. end;
  504. {******************************************************************
  505. ObjC type validity checking
  506. *******************************************************************}
  507. function objcdochecktype(def: tdef; recordinfostate: trecordinfostate; out founderror: tdef): boolean; forward;
  508. function checkrecsttype(recst: tabstractrecordsymtable; recordinfostate: trecordinfostate; out founderror: tdef): boolean;
  509. var
  510. i: longint;
  511. field: tfieldvarsym;
  512. newstate: trecordinfostate;
  513. begin
  514. result:=false;
  515. newstate:=recordinfostate;
  516. { Although we never have to print the type info for nested
  517. records, check them anyway in case we're not after a pointer
  518. since if such records contain refcounted types then they
  519. can cause just as much trouble as if they were a simple
  520. refcounted field. }
  521. if (newstate=ris_afterpointer) then
  522. newstate:=ris_dontprint;
  523. for i:=0 to recst.symlist.count-1 do
  524. begin
  525. if (tsym(recst.symlist[i]).typ<>fieldvarsym) then
  526. continue;
  527. field:=tfieldvarsym(recst.symlist[i]);
  528. if not objcdochecktype(field.vardef,newstate,founderror) then
  529. exit;
  530. end;
  531. result:=true
  532. end;
  533. function objcdochecktype(def: tdef; recordinfostate: trecordinfostate; out founderror: tdef): boolean;
  534. var
  535. recdef: trecorddef;
  536. objdef: tobjectdef;
  537. newstate: trecordinfostate;
  538. begin
  539. result:=true;
  540. case def.typ of
  541. stringdef :
  542. begin
  543. case tstringdef(def).stringtype of
  544. st_shortstring:
  545. ;
  546. else
  547. { While we could handle refcounted Pascal strings correctly
  548. when such methods are called from Pascal code, things would
  549. completely break down if they were called from Objective-C
  550. code/reflection since the necessary refcount helper calls
  551. would be missing on the caller side (unless we'd
  552. automatically generate wrappers). }
  553. result:=false;
  554. end;
  555. end;
  556. enumdef,
  557. orddef :
  558. ;
  559. pointerdef :
  560. begin
  561. newstate:=recordinfostate;
  562. if (recordinfostate<ris_dontprint) then
  563. newstate:=succ(newstate);
  564. if not objcdochecktype(tpointerdef(def).pointeddef,newstate,founderror) then
  565. begin
  566. result:=false;
  567. { report the exact (nested) error defintion }
  568. exit;
  569. end;
  570. end;
  571. floatdef :
  572. begin
  573. case tfloatdef(def).floattype of
  574. s32real,
  575. s64real:
  576. ;
  577. else
  578. result:=false;
  579. end;
  580. end;
  581. filedef :
  582. result:=false;
  583. recorddef :
  584. begin
  585. if (recordinfostate<>ris_dontprint) then
  586. begin
  587. if not checkrecsttype(tabstractrecordsymtable(trecorddef(def).symtable),recordinfostate,founderror) then
  588. begin
  589. result:=false;
  590. { report the exact (nested) error defintion }
  591. exit;
  592. end
  593. end
  594. end;
  595. variantdef :
  596. begin
  597. recdef:=trecorddef(search_system_type('TVARDATA').typedef);
  598. if (recordinfostate<>ris_dontprint) then
  599. begin
  600. if not checkrecsttype(tabstractrecordsymtable(recdef.symtable),recordinfostate,founderror) then
  601. begin
  602. result:=false;
  603. { report the exact (nested) error defintion }
  604. exit;
  605. end
  606. end;
  607. end;
  608. classrefdef:
  609. begin
  610. if is_objcclassref(def) then
  611. begin
  612. objdef:=tobjectdef(tclassrefdef(def).pointeddef);
  613. newstate:=recordinfostate;
  614. if (recordinfostate<ris_dontprint) then
  615. newstate:=succ(newstate);
  616. if (newstate<>ris_dontprint) then
  617. begin
  618. if not checkrecsttype(tabstractrecordsymtable(objdef.symtable),recordinfostate,founderror) then
  619. begin
  620. result:=false;
  621. { report the exact (nested) error defintion }
  622. exit;
  623. end
  624. end
  625. end
  626. end;
  627. setdef,
  628. formaldef :
  629. ;
  630. arraydef :
  631. begin
  632. if is_array_of_const(def) then
  633. { ok, varargs are ignored in signatures }
  634. else if is_special_array(def) then
  635. result:=false
  636. else
  637. begin
  638. if not is_packed_array(def) then
  639. begin
  640. if not objcdochecktype(tarraydef(def).elementdef,ris_initial,founderror) then
  641. begin
  642. result:=false;
  643. { report the exact (nested) error defintion }
  644. exit;
  645. end;
  646. end;
  647. end;
  648. end;
  649. procvardef :
  650. ;
  651. objectdef :
  652. case tobjectdef(def).objecttype of
  653. odt_class,
  654. odt_object,
  655. odt_cppclass:
  656. begin
  657. newstate:=recordinfostate;
  658. { implicit pointer for classes }
  659. if (tobjectdef(def).objecttype=odt_class) then
  660. begin
  661. if (recordinfostate<ris_dontprint) then
  662. newstate:=succ(newstate);
  663. end;
  664. if newstate<>ris_dontprint then
  665. begin
  666. if not checkrecsttype(tabstractrecordsymtable(tobjectdef(def).symtable),newstate,founderror) then
  667. begin
  668. result:=false;
  669. { report the exact (nested) error defintion }
  670. exit;
  671. end
  672. end
  673. end;
  674. odt_interfacecom,
  675. odt_interfacecom_property,
  676. odt_interfacecom_function,
  677. odt_dispinterface:
  678. result:=false;
  679. odt_interfacecorba,
  680. odt_objcclass,
  681. odt_objcprotocol:
  682. ;
  683. else
  684. internalerror(2009081709);
  685. end;
  686. undefineddef,
  687. errordef :
  688. result:=false;
  689. procdef :
  690. result:=false;
  691. else
  692. internalerror(2009170812);
  693. end;
  694. if not result then
  695. founderror:=def;
  696. end;
  697. function objcchecktype(def: tdef; out founderror: tdef): boolean;
  698. begin
  699. result:=objcdochecktype(def,ris_initial,founderror);
  700. end;
  701. end.