aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenObjC/attr-noreturn.m
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenObjC/attr-noreturn.m')
-rw-r--r--test/CodeGenObjC/attr-noreturn.m99
1 files changed, 99 insertions, 0 deletions
diff --git a/test/CodeGenObjC/attr-noreturn.m b/test/CodeGenObjC/attr-noreturn.m
new file mode 100644
index 000000000000..c413d0557ad2
--- /dev/null
+++ b/test/CodeGenObjC/attr-noreturn.m
@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-MRC
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-ARC
+
+__attribute__((objc_root_class))
+@interface Root
+- (instancetype) init;
+@end
+
+@interface Base : Root
+@end
+
+@interface Middle : Base
++ (void) abort __attribute__((noreturn));
+- (void) fail __attribute__((noreturn));
+@end
+
+@interface Derived : Middle
+@end
+
+// An arbitrary instance pointer may be null.
+void testInstanceMethod(Derived *x) {
+ [x fail];
+}
+// CHECK-LABEL: @testInstanceMethod
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}}
+
+// A direct call of a class method will normally never have a null receiver.
+void testClassMethod() {
+ [Derived abort];
+}
+// CHECK-LABEL: @testClassMethod
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NORETURN:#[0-9]+]]
+
+__attribute__((weak_import))
+@interface WeakMiddle : Base
+@end
+
+@interface WeakDerived : WeakMiddle
++ (void) abort __attribute__((noreturn));
+@end
+
+// The class pointer of a weakly-imported class may be null.
+void testWeakImport() {
+ [WeakDerived abort];
+}
+// CHECK-LABEL: @testWeakImport
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}}
+
+@interface Derived (MyMethods)
+@end
+
+@implementation Derived (MyMethods)
+
+// In general, self can be reassigned, so we can't make stronger assumptions.
+// But ARC makes self const in an ordinary method.
+// TODO: do the analysis to take advantage of the dominant case where
+// self is not reassigned.
+- (void) testSelfInstanceMethod {
+ [self fail];
+}
+// CHECK-LABEL: [Derived(MyMethods) testSelfInstanceMethod]
+// CHECK-MRC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}}
+// CHECK-ARC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NORETURN]]
+
+// The ARC rule doesn't apply in -init methods.
+- (id) initWhileTestingSelfInstanceMethod {
+ self = [super init];
+ [self fail];
+ return self;
+}
+// CHECK-LABEL: [Derived(MyMethods) initWhileTestingSelfInstanceMethod]
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}}
+
+// Same thing applies to class methods.
++ (void) testSelfClassMethod {
+ [self abort];
+}
+// CHECK-LABEL: [Derived(MyMethods) testSelfClassMethod]
+// CHECK-MRC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}){{$}}
+// CHECK-ARC: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*)*)(i8* {{.*}}, i8* {{.*}}) [[NORETURN]]
+
+// Super invocations may never be used with a null pointer; this is a
+// constraint on user code when it isn't enforced by the ARC const-self
+// rule.
+- (void) testSuperInstanceMethod {
+ [super fail];
+}
+// CHECK-LABEL: [Derived(MyMethods) testSuperInstanceMethod]
+// CHECK: call void bitcast (i8* ([[SUPER_T:%.*]]*, i8*, ...)* @objc_msgSendSuper2 to void ([[SUPER_T]]*, i8*)*)([[SUPER_T]]* {{.*}}, i8* {{.*}}) [[NORETURN]]
+
++ (void) testSuperClassMethod {
+ [super abort];
+}
+// CHECK-LABEL: [Derived(MyMethods) testSuperClassMethod]
+// CHECK: call void bitcast (i8* ([[SUPER_T]]*, i8*, ...)* @objc_msgSendSuper2 to void ([[SUPER_T]]*, i8*)*)([[SUPER_T]]* {{.*}}, i8* {{.*}}) [[NORETURN]]
+@end
+
+// CHECK: attributes [[NORETURN]] = { noreturn }
+ \ No newline at end of file