objcutil.pas 29 KB

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