Add "Wno-objc-root-class" to tests in the Objective-C suite where needed. gcc/testsuite/ChangeLog: PR objc/77404 * objc.dg/anon-1.m: Add Wno-objc-root-class. * objc.dg/attributes/class-attribute-1.m: Likewise. * objc.dg/attributes/class-attribute-2.m: Likewise. * objc.dg/attributes/class-attribute-3.m: Likewise. * objc.dg/attributes/method-deprecated-1.m: Likewise. * objc.dg/attributes/method-deprecated-2.m: Likewise. * objc.dg/attributes/method-deprecated-3.m: Likewise. * objc.dg/attributes/method-format-1.m: Likewise. * objc.dg/attributes/method-nonnull-1.m: Likewise. * objc.dg/attributes/method-noreturn-1.m: Likewise. * objc.dg/attributes/method-sentinel-1.m: Likewise. * objc.dg/attributes/nsobject-01.m: Likewise. * objc.dg/attributes/objc-exception-1.m: Likewise. * objc.dg/attributes/parameter-attribute-1.m: Likewise. * objc.dg/attributes/parameter-attribute-2.m: Likewise. * objc.dg/attributes/proto-attribute-1.m: Likewise. * objc.dg/attributes/proto-attribute-2.m: Likewise. * objc.dg/attributes/proto-attribute-3.m: Likewise. * objc.dg/attributes/proto-attribute-4.m: Likewise. * objc.dg/bitfield-2.m: Likewise. * objc.dg/break-in-ifstmt.m: Likewise. * objc.dg/class-1.m: Likewise. * objc.dg/class-extension-1.m: Likewise. * objc.dg/class-extension-2.m: Likewise. * objc.dg/class-extension-3.m: Likewise. * objc.dg/class-extension-4.m: Likewise. * objc.dg/class-protocol-1.m: Likewise. * objc.dg/comp-types-7.m: Likewise. * objc.dg/demangle-1.m: Likewise. * objc.dg/duplicate-class-1.m: Likewise. * objc.dg/encode-6-next.m: Likewise. * objc.dg/encode-6.m: Likewise. * objc.dg/enhanced-proto-2.m: Likewise. * objc.dg/exceptions-1.m: Likewise. * objc.dg/exceptions-3.m: Likewise. * objc.dg/exceptions-4.m: Likewise. * objc.dg/exceptions-5.m: Likewise. * objc.dg/fobjc-std-1.m: Likewise. * objc.dg/foreach-2.m: Likewise. * objc.dg/foreach-4.m: Likewise. * objc.dg/foreach-5.m: Likewise. * objc.dg/fsyntax-only.m: Likewise. * objc.dg/gnu-api-2-class-meta.m: Likewise. * objc.dg/gnu-api-2-class.m: Likewise. * objc.dg/gnu-api-2-ivar.m: Likewise. * objc.dg/gnu-api-2-method.m: Likewise. * objc.dg/gnu-api-2-objc.m: Likewise. * objc.dg/gnu-api-2-objc_msg_lookup.m: Likewise. * objc.dg/gnu-api-2-object.m: Likewise. * objc.dg/gnu-api-2-property.m: Likewise. * objc.dg/gnu-api-2-protocol.m: Likewise. * objc.dg/gnu-api-2-resolve-method.m: Likewise. * objc.dg/gnu-api-2-sel.m: Likewise. * objc.dg/incomplete-type-1.m: Likewise. * objc.dg/instancetype-0.m: Likewise. * objc.dg/invalid-method-2.m: Likewise. * objc.dg/ivar-invalid-type-1.m: Likewise. * objc.dg/ivar-problem-1.m: Likewise. * objc.dg/ivar-scope-1.m: Likewise. * objc.dg/ivar-scope-2.m: Likewise. * objc.dg/ivar-scope-4.m: Likewise. * objc.dg/ivar-visibility-1.m: Likewise. * objc.dg/ivar-visibility-2.m: Likewise. * objc.dg/ivar-visibility-3.m: Likewise. * objc.dg/ivar-visibility-4.m: Likewise. * objc.dg/local-decl-1.m: Likewise. * objc.dg/lto/lto.exp: Likewise. * objc.dg/lto/trivial-1_0.m: Likewise. * objc.dg/method-1.m: Likewise. * objc.dg/method-12.m: Likewise. * objc.dg/method-13.m: Likewise. * objc.dg/method-14.m: Likewise. * objc.dg/missing-proto-3.m: Likewise. * objc.dg/next-runtime-1.m: Likewise. * objc.dg/objc-foreach-1.m: Likewise. * objc.dg/objc-foreach-2.m: Likewise. * objc.dg/objc-foreach-3.m: Likewise. * objc.dg/objc-nofilename-1.m: Likewise. * objc.dg/param-1.m: Likewise. * objc.dg/pch/pch.exp: Likewise. * objc.dg/plugin/diagnostic-test-expressions-1.m: Likewise. * objc.dg/pr23709.m: Likewise. * objc.dg/private-1.m: Likewise. * objc.dg/private-2.m: Likewise. * objc.dg/property/property.exp: Likewise. * objc.dg/proto-hier-1.m: Likewise. * objc.dg/proto-hier-2.m: Likewise. * objc.dg/proto-lossage-1.m: Likewise. * objc.dg/proto-lossage-5.m: Likewise. * objc.dg/proto-qual-1.m: Likewise. * objc.dg/protocol-inheritance-1.m: Likewise. * objc.dg/protocol-inheritance-2.m: Likewise. * objc.dg/protocol-optional-1.m: Likewise. * objc.dg/selector-1.m: Likewise. * objc.dg/selector-2.m: Likewise. * objc.dg/selector-3.m: Likewise. * objc.dg/selector-4.m: Likewise. * objc.dg/shadow-1.m: Likewise. * objc.dg/shadow-2.m: Likewise. * objc.dg/special/load-category-1.m: Likewise. * objc.dg/special/load-category-2.m: Likewise. * objc.dg/special/load-category-3.m: Likewise. * objc.dg/special/special.exp: Likewise. * objc.dg/special/unclaimed-category-1.h: Likewise. * objc.dg/special/unclaimed-category-1.m: Likewise. * objc.dg/stabs-1.m: Likewise. * objc.dg/strings/strings.exp: Likewise. * objc.dg/stubify-1.m: Likewise. * objc.dg/stubify-2.m: Likewise. * objc.dg/super-class-2.m: Likewise. * objc.dg/super-dealloc-1.m: Likewise. * objc.dg/super-dealloc-2.m: Likewise. * objc.dg/sync-3.m: Likewise. * objc.dg/threedotthree-abi-1.m: Likewise. * objc.dg/torture/dg-torture.exp: Likewise. * objc.dg/torture/strings/strings.exp: Likewise. * objc.dg/try-catch-11.m: Likewise. * objc.dg/try-catch-12.m: Likewise. * objc.dg/type-size-2.m: Likewise. * objc.dg/type-size-3.m: Likewise. * objc.dg/type-size-4.m: Likewise. * objc.dg/type-size-5.m: Likewise. * objc.dg/undeclared-selector.m: Likewise. * objc.dg/volatile-1.m: Likewise.
569 lines
14 KiB
Objective-C
569 lines
14 KiB
Objective-C
/* Test the Modern GNU Objective-C Runtime API.
|
|
|
|
This is test 'resolve-method', covering +resolveClassMethod: and
|
|
+resolveInstanceMethod:. */
|
|
|
|
/* { dg-do run } */
|
|
/* { dg-skip-if "" { *-*-* } { "-fnext-runtime" } { "" } } */
|
|
/* { dg-additional-options "-Wno-objc-root-class" } */
|
|
|
|
/* To get the modern GNU Objective-C Runtime API, you include
|
|
objc/runtime.h. */
|
|
#include <objc/runtime.h>
|
|
|
|
/* For __objc_msg_forward2. */
|
|
#include <objc/message.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
@interface MyRootClass
|
|
{ Class isa; }
|
|
+ alloc;
|
|
- init;
|
|
@end
|
|
|
|
@implementation MyRootClass
|
|
+ alloc { return class_createInstance (self, 0); }
|
|
- init { return self; }
|
|
@end
|
|
|
|
|
|
/* A number of tests will try invoking methods that don't exist. We
|
|
want to record the fact, but not abort the program, so we supply
|
|
our own fowarding implementation which will invoke the following
|
|
function for any method that is not found. */
|
|
|
|
/* Keep track of how many times a non-existing method was executed. */
|
|
static int nonExistingMethodCount = 0;
|
|
|
|
/* Inspired by nil_method in libobjc. */
|
|
id nonExisting_method (id receiver __attribute__ ((__unused__)),
|
|
SEL sel __attribute__ ((__unused__)))
|
|
{
|
|
nonExistingMethodCount++;
|
|
return nil;
|
|
}
|
|
|
|
/* Keep track of how many times the forwarding lookup was invoked. */
|
|
static int forwardingCount = 0;
|
|
|
|
/* We install this forwarding hook to cause all failed method lookups
|
|
to call our 'nonExisting_method' function. */
|
|
IMP forward_everything_to_non_existing_method (id receiver __attribute__ ((__unused__)),
|
|
SEL sel __attribute__ ((__unused__)))
|
|
{
|
|
forwardingCount++;
|
|
return (IMP)nonExisting_method;
|
|
}
|
|
|
|
|
|
/* 'CountClass' is used to test that +resolveClassMethod: and
|
|
+resolveInstanceMethod: are called when expected. They do nothing
|
|
other than recording that they are called. */
|
|
@interface CountClass : MyRootClass
|
|
+ (BOOL) resolveClassMethod: (SEL)selector;
|
|
+ (BOOL) resolveInstanceMethod: (SEL)selector;
|
|
+ (void) existingClassMethod;
|
|
- (void) existingInstanceMethod;
|
|
@end
|
|
|
|
/* Count how many times the methods are called for class
|
|
'CountClass'. */
|
|
static int resolveClassMethodCount = 0;
|
|
static int resolveInstanceMethodCount = 0;
|
|
|
|
@implementation CountClass : MyRootClass
|
|
+ (BOOL) resolveClassMethod: (SEL)selector
|
|
{
|
|
resolveClassMethodCount++;
|
|
return NO;
|
|
}
|
|
+ (BOOL) resolveInstanceMethod: (SEL)selector
|
|
{
|
|
resolveInstanceMethodCount++;
|
|
return NO;
|
|
}
|
|
+ (void) existingClassMethod
|
|
{
|
|
return;
|
|
}
|
|
- (void) existingInstanceMethod
|
|
{
|
|
return;
|
|
}
|
|
@end
|
|
|
|
@protocol NonExistingStuff
|
|
+ (void) nonExistingClassMethod;
|
|
- (void) nonExistingInstanceMethod;
|
|
@end
|
|
|
|
/* Declare a category with some non existing methods, but don't
|
|
actually implement them. */
|
|
@interface CountClass (NonExistingStuff) <NonExistingStuff>
|
|
@end
|
|
|
|
|
|
/* 'SelfExtendingClass' is used to test that +resolveClassMethod: and
|
|
+resolveInstanceMethod: can extend the class. Any time they are
|
|
called, they install the requested method, mapping it to the same
|
|
implementation as 'countHits'. */
|
|
@interface SelfExtendingClass : MyRootClass
|
|
+ (int) countHits;
|
|
+ (BOOL) resolveClassMethod: (SEL)selector;
|
|
+ (BOOL) resolveInstanceMethod: (SEL)selector;
|
|
@end
|
|
|
|
/* How many times the countHits method (or a clone) was called. */
|
|
static int hitCount = 0;
|
|
|
|
@implementation SelfExtendingClass : MyRootClass
|
|
+ (int) countHits
|
|
{
|
|
hitCount++;
|
|
return hitCount;
|
|
}
|
|
+ (BOOL) resolveClassMethod: (SEL)selector
|
|
{
|
|
/* Duplicate the 'countHits' method into the new method. */
|
|
Method method = class_getClassMethod (self, @selector (countHits));
|
|
class_addMethod (object_getClass (self), selector,
|
|
method_getImplementation (method),
|
|
method_getTypeEncoding (method));
|
|
resolveClassMethodCount++;
|
|
return YES;
|
|
}
|
|
+ (BOOL) resolveInstanceMethod: (SEL)selector
|
|
{
|
|
/* Duplicate the 'countHits' method into the new method. */
|
|
Method method = class_getClassMethod (self, @selector (countHits));
|
|
class_addMethod (self, selector,
|
|
method_getImplementation (method),
|
|
method_getTypeEncoding (method));
|
|
resolveInstanceMethodCount++;
|
|
return YES;
|
|
|
|
}
|
|
@end
|
|
|
|
@protocol NonExistingStuff2
|
|
+ (int) nonExistingCountHitsMethod;
|
|
- (int) nonExistingCountHitsMethod;
|
|
|
|
+ (int) nonExistingCountHitsMethod2;
|
|
- (int) nonExistingCountHitsMethod2;
|
|
|
|
+ (int) nonExistingCountHitsMethod3;
|
|
- (int) nonExistingCountHitsMethod3;
|
|
@end
|
|
|
|
/* Declare a category with some non existing methods, but don't
|
|
actually implement them. */
|
|
@interface SelfExtendingClass (NonExistingStuff) <NonExistingStuff2>
|
|
@end
|
|
|
|
|
|
int main (int argc, void **args)
|
|
{
|
|
/* Functions are tested in alphabetical order. */
|
|
|
|
/* Install our test forwarding hook. */
|
|
__objc_msg_forward2 = forward_everything_to_non_existing_method;
|
|
|
|
printf ("Testing [+resolveClassMethod:]...\n");
|
|
{
|
|
Method m;
|
|
IMP i;
|
|
|
|
/** CountClass tests. **/
|
|
|
|
/* Call an existing method. No +resolveClassMethod and no
|
|
forwarding should be triggered. */
|
|
[CountClass existingClassMethod];
|
|
|
|
if (resolveClassMethodCount != 0)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Call a non-existing method. Both +resolveClassMethod and the
|
|
forwarding should be triggered. */
|
|
[CountClass nonExistingClassMethod];
|
|
|
|
if (resolveClassMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
/* Now try the same tests with class_getClassMethod(), which
|
|
should trigger the resolve methods too, but not the
|
|
forwarding. */
|
|
m = class_getClassMethod (objc_getClass ("CountClass"),
|
|
@selector (existingClassMethod));
|
|
if (resolveClassMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
m = class_getClassMethod (objc_getClass ("CountClass"),
|
|
@selector (nonExistingClassMethod));
|
|
if (resolveClassMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
/* Now try the same tests with class_getMethodImplementation(),
|
|
which should trigger the resolve methods and the forwarding
|
|
(but not execute the forwarding, obviously). */
|
|
i = class_getMethodImplementation (object_getClass (objc_getClass ("CountClass")),
|
|
@selector (existingClassMethod));
|
|
if (resolveClassMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
i = class_getMethodImplementation (object_getClass (objc_getClass ("CountClass")),
|
|
@selector (nonExistingClassMethod));
|
|
if (resolveClassMethodCount != 3)
|
|
abort ();
|
|
|
|
if (forwardingCount != 2)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
|
|
/* Reset the counters for the next test. */
|
|
resolveClassMethodCount = 0;
|
|
forwardingCount = 0;
|
|
nonExistingMethodCount = 0;
|
|
|
|
|
|
/** SelfExtendingClass tests. **/
|
|
|
|
/* Try the direct countHits method first. No resolving or
|
|
forwarding should be triggered. */
|
|
if ([SelfExtendingClass countHits] != 1)
|
|
abort ();
|
|
|
|
if (resolveClassMethodCount != 0)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Now, try calling a non-existing count method; it should be
|
|
installed and invoked. */
|
|
if ([SelfExtendingClass nonExistingCountHitsMethod] != 2)
|
|
abort ();
|
|
|
|
if (resolveClassMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Try it again. The method has now been installed, so it should
|
|
be used and work, but with no additional resolving
|
|
involved. */
|
|
if ([SelfExtendingClass nonExistingCountHitsMethod] != 3)
|
|
abort ();
|
|
|
|
if (resolveClassMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
|
|
/* Now try the same tests with class_getClassMethod(). */
|
|
m = class_getClassMethod (objc_getClass ("SelfExtendingClass"),
|
|
@selector (nonExistingCountHitsMethod2));
|
|
if (resolveClassMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Try it again. The method has now been installed, so it should
|
|
be used and work, but with no additional resolving
|
|
involved. */
|
|
if ([SelfExtendingClass nonExistingCountHitsMethod2] != 4)
|
|
abort ();
|
|
|
|
if (resolveClassMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
|
|
/* Now try the same tests with class_getMethodImplementation(). */
|
|
i = class_getMethodImplementation (object_getClass (objc_getClass ("SelfExtendingClass")),
|
|
@selector (nonExistingCountHitsMethod3));
|
|
if (resolveClassMethodCount != 3)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Try it again. The method has now been installed, so it should
|
|
be used and work, but with no additional resolving
|
|
involved. */
|
|
if ([SelfExtendingClass nonExistingCountHitsMethod3] != 5)
|
|
abort ();
|
|
|
|
if (resolveClassMethodCount != 3)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
}
|
|
|
|
/* Reset the counters for the next test. */
|
|
nonExistingMethodCount = 0;
|
|
forwardingCount = 0;
|
|
hitCount = 0;
|
|
|
|
printf ("Testing [+resolveInstanceMethod:]...\n");
|
|
{
|
|
Method m;
|
|
IMP i;
|
|
CountClass *object = [[CountClass alloc] init];
|
|
SelfExtendingClass *object2 = [[SelfExtendingClass alloc] init];
|
|
|
|
/** CountClass tests. **/
|
|
|
|
/* Call an existing method. No +resolveInstanceMethod and no
|
|
forwarding should be triggered. */
|
|
[object existingInstanceMethod];
|
|
|
|
if (resolveInstanceMethodCount != 0)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Call a non-existing method. Both +resolveInstanceMethod and the
|
|
forwarding should be triggered. */
|
|
[object nonExistingInstanceMethod];
|
|
|
|
if (resolveInstanceMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
/* Now try the same tests with class_getInstanceMethod(), which
|
|
should trigger the resolve methods too, but not the
|
|
forwarding. */
|
|
m = class_getInstanceMethod (objc_getClass ("CountClass"),
|
|
@selector (existingInstanceMethod));
|
|
|
|
if (resolveInstanceMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
m = class_getInstanceMethod (objc_getClass ("CountClass"),
|
|
@selector (nonExistingInstanceMethod));
|
|
|
|
if (resolveInstanceMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
/* Now try the same tests with class_getMethodImplementation(),
|
|
which should trigger the resolve methods and the
|
|
forwarding. */
|
|
i = class_getMethodImplementation (objc_getClass ("CountClass"),
|
|
@selector (existingInstanceMethod));
|
|
if (resolveInstanceMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 1)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
i = class_getMethodImplementation (objc_getClass ("CountClass"),
|
|
@selector (nonExistingInstanceMethod));
|
|
if (resolveInstanceMethodCount != 3)
|
|
abort ();
|
|
|
|
if (forwardingCount != 2)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 1)
|
|
abort ();
|
|
|
|
/* Reset the counters for the next test. */
|
|
resolveInstanceMethodCount = 0;
|
|
forwardingCount = 0;
|
|
nonExistingMethodCount = 0;
|
|
|
|
|
|
/** SelfExtendingClass tests. **/
|
|
|
|
/* Try the direct countHits method first. No resolving or
|
|
forwarding should be triggered. */
|
|
if ([SelfExtendingClass countHits] != 1)
|
|
abort ();
|
|
|
|
if (resolveInstanceMethodCount != 0)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Now, try calling a non-existing count method; it should be
|
|
installed and invoked. */
|
|
if ([object2 nonExistingCountHitsMethod] != 2)
|
|
abort ();
|
|
|
|
if (resolveInstanceMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Try it again. The method has now been installed, so it should
|
|
be used and work, but with no additional resolving
|
|
involved. */
|
|
if ([object2 nonExistingCountHitsMethod] != 3)
|
|
abort ();
|
|
|
|
if (resolveInstanceMethodCount != 1)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Now try the same tests with class_getInstanceMethod(). */
|
|
m = class_getInstanceMethod (objc_getClass ("SelfExtendingClass"),
|
|
@selector (nonExistingCountHitsMethod2));
|
|
if (resolveInstanceMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Try it again. The method has now been installed, so it should
|
|
be used and work, but with no additional resolving
|
|
involved. */
|
|
if ([object2 nonExistingCountHitsMethod2] != 4)
|
|
abort ();
|
|
|
|
if (resolveInstanceMethodCount != 2)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
|
|
/* Now try the same tests with class_getMethodImplementation(). */
|
|
i = class_getMethodImplementation (objc_getClass ("SelfExtendingClass"),
|
|
@selector (nonExistingCountHitsMethod3));
|
|
if (resolveInstanceMethodCount != 3)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
|
|
/* Try it again. The method has now been installed, so it should
|
|
be used and work, but with no additional resolving
|
|
involved. */
|
|
if ([object2 nonExistingCountHitsMethod3] != 5)
|
|
abort ();
|
|
|
|
if (resolveInstanceMethodCount != 3)
|
|
abort ();
|
|
|
|
if (forwardingCount != 0)
|
|
abort ();
|
|
|
|
if (nonExistingMethodCount != 0)
|
|
abort ();
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|