diff --git a/Test/FastPathAlloc.m b/Test/FastPathAlloc.m index 5aaf9e04..340a8dd3 100644 --- a/Test/FastPathAlloc.m +++ b/Test/FastPathAlloc.m @@ -21,6 +21,8 @@ @interface NoAlloc : Test @end @interface NoInit : Test @end @interface NoInit2 : NoInit @end +@interface ShouldInitSubclassed : NoInit @end + @implementation ShouldAlloc + (instancetype)alloc { @@ -91,6 +93,13 @@ + (instancetype)alloc } @end +@implementation ShouldInitSubclassed ++ (instancetype) alloc +{ + return [ShouldInit alloc]; +} +@end + Class getClassNamed(char *name) { return nil; @@ -114,6 +123,10 @@ int main(void) [[ShouldInit2 alloc] init]; assert(called); + called = NO; + [[ShouldInitSubclassed alloc] init]; + assert(called); + called = NO; [NoAlloc alloc]; assert(!called); diff --git a/fast_paths.m b/fast_paths.m index c9715650..ec2f646a 100644 --- a/fast_paths.m +++ b/fast_paths.m @@ -9,9 +9,6 @@ - (id)init; @end #include -/** - * Equivalent to [cls alloc]. If there's a fast path opt-in, then this skips the message send. - */ OBJC_PUBLIC id objc_alloc(Class cls) @@ -66,6 +63,9 @@ - (id)init; return nil; } id instance = objc_alloc(cls); + // If +alloc was overwritten, it is not guaranteed that it returns + // an instance of cls. + cls = classForObject(instance); if (objc_test_class_flag(cls, objc_class_flag_fast_alloc_init)) { return instance;