aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenObjCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/CodeGenObjCXX')
-rw-r--r--test/CodeGenObjCXX/arc-attrs-abi.mm38
-rw-r--r--test/CodeGenObjCXX/arc-blocks.mm2
-rw-r--r--test/CodeGenObjCXX/arc-move.mm8
-rw-r--r--test/CodeGenObjCXX/arc-references.mm10
-rw-r--r--test/CodeGenObjCXX/arc.mm6
-rw-r--r--test/CodeGenObjCXX/encode.mm2
-rw-r--r--test/CodeGenObjCXX/lambda-expressions.mm13
-rw-r--r--test/CodeGenObjCXX/lambda-to-block.mm18
-rw-r--r--test/CodeGenObjCXX/literals.mm10
-rw-r--r--test/CodeGenObjCXX/objc-weak.mm69
-rw-r--r--test/CodeGenObjCXX/objfw-exceptions.mm17
11 files changed, 174 insertions, 19 deletions
diff --git a/test/CodeGenObjCXX/arc-attrs-abi.mm b/test/CodeGenObjCXX/arc-attrs-abi.mm
new file mode 100644
index 000000000000..14bdf8be30e5
--- /dev/null
+++ b/test/CodeGenObjCXX/arc-attrs-abi.mm
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple x86_64-apple -emit-llvm -fobjc-arc -o - %s -std=c++11 | FileCheck %s --check-prefix=ITANIUM
+// RUN: %clang_cc1 -triple x86_64-windows -emit-llvm -fobjc-arc -o - %s -std=c++11
+//
+// Test cases where we weren't properly adding extended parameter info, which
+// caused assertions to fire. Hence, minimal CHECKs.
+
+struct VirtualBase {
+ VirtualBase(__attribute__((ns_consumed)) id x,
+ void * __attribute__((pass_object_size(0))));
+};
+struct WithVirtualBase : virtual VirtualBase {
+ WithVirtualBase(__attribute__((ns_consumed)) id x);
+};
+
+WithVirtualBase::WithVirtualBase(__attribute__((ns_consumed)) id x)
+ : VirtualBase(x, (void *)0) {}
+
+
+struct VirtualBase2 {
+ VirtualBase2(__attribute__((ns_consumed)) id x, void *y);
+};
+
+// In this case, we don't actually end up passing the `id` param from
+// WithVirtualBaseLast's ctor to WithVirtualBaseMid's. So, we shouldn't emit
+// ext param info for `id` to `Mid`. Itanium-only check since MSABI seems to
+// emit the construction code inline.
+struct WithVirtualBaseMid : virtual VirtualBase2 {
+ // Ensure we only pass in `this` and a vtable. Otherwise this test is useless.
+ // ITANIUM: define {{.*}} void @_ZN18WithVirtualBaseMidCI212VirtualBase2EP11objc_objectPv({{[^,]*}}, {{[^,]*}})
+ using VirtualBase2::VirtualBase2;
+};
+struct WithVirtualBaseLast : WithVirtualBaseMid {
+ using WithVirtualBaseMid::WithVirtualBaseMid;
+};
+
+void callLast(__attribute__((ns_consumed)) id x) {
+ WithVirtualBaseLast{x, (void*)0};
+}
diff --git a/test/CodeGenObjCXX/arc-blocks.mm b/test/CodeGenObjCXX/arc-blocks.mm
index 2bae18a19b3f..1e439578e8e9 100644
--- a/test/CodeGenObjCXX/arc-blocks.mm
+++ b/test/CodeGenObjCXX/arc-blocks.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck %s
// CHECK: [[A:.*]] = type { i64, [10 x i8*] }
diff --git a/test/CodeGenObjCXX/arc-move.mm b/test/CodeGenObjCXX/arc-move.mm
index 7437d6b6c7f9..def2cea95647 100644
--- a/test/CodeGenObjCXX/arc-move.mm
+++ b/test/CodeGenObjCXX/arc-move.mm
@@ -49,7 +49,7 @@ void library_move(__strong id &y) {
// CHECK: [[X:%.*]] = alloca i8*, align 8
// CHECK: [[I:%.*]] = alloca i32, align 4
// CHECK: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XPTR1]])
// CHECK: [[Y:%[a-zA-Z0-9]+]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_
// Load the object
// CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[Y]]
@@ -60,15 +60,15 @@ void library_move(__strong id &y) {
id x = move(y);
// CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[IPTR1]])
// CHECK-NEXT: store i32 17
int i = 17;
// CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[IPTR2]])
// CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[OBJ]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenObjCXX/arc-references.mm b/test/CodeGenObjCXX/arc-references.mm
index c62df4e49bb6..983b211dfbfa 100644
--- a/test/CodeGenObjCXX/arc-references.mm
+++ b/test/CodeGenObjCXX/arc-references.mm
@@ -21,7 +21,7 @@ void test0() {
// CHECK: call void @_Z6calleev
callee();
// CHECK: call void @objc_release
- // CHECK-NEXT: ret
+ // CHECK: ret
}
// No lifetime extension when we're binding a reference to an lvalue.
@@ -44,9 +44,9 @@ void test3() {
const __weak id &ref = strong_id();
// CHECK-NEXT: call void @_Z6calleev()
callee();
- // CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR]])
// CHECK-NEXT: call void @objc_destroyWeak
+ // CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTR]])
// CHECK-NEXT: ret void
}
@@ -75,11 +75,11 @@ void test5(__strong id &x) {
// CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8*
// CHECK-NEXT: call void @objc_release
// CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[IPTR1]])
// CHECK-NEXT: store i32 17, i32
int i = 17;
// CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[IPTR2]])
// CHECK-NEXT: ret void
}
diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm
index b9d2c4de2fcd..5e66206ad547 100644
--- a/test/CodeGenObjCXX/arc.mm
+++ b/test/CodeGenObjCXX/arc.mm
@@ -65,10 +65,10 @@ void test34(int cond) {
// CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1
// CHECK-NEXT: store i32
// CHECK-NEXT: [[STRONGP:%.*]] = bitcast i8** [[STRONG]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGP]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[STRONGP]])
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: [[WEAKP:%.*]] = bitcast i8** [[WEAK]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKP]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[WEAKP]])
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
@@ -316,7 +316,7 @@ template void test40_helper<int>();
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
// CHECK-NEXT: [[XP:%.*]] = bitcast i8** [[X]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XP]])
+// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[XP]])
// CHECK-NEXT: store i8* null, i8** [[X]]
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]]
diff --git a/test/CodeGenObjCXX/encode.mm b/test/CodeGenObjCXX/encode.mm
index 5bb4a1ecfa9b..e4c7618f50c2 100644
--- a/test/CodeGenObjCXX/encode.mm
+++ b/test/CodeGenObjCXX/encode.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -std=gnu++98 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
// CHECK: v17@0:8{vector<float, float, float>=}16
// CHECK: {vector<float, float, float>=}
diff --git a/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm
index 7ac7a2137fb4..c8247e2e0a26 100644
--- a/test/CodeGenObjCXX/lambda-expressions.mm
+++ b/test/CodeGenObjCXX/lambda-expressions.mm
@@ -71,6 +71,10 @@ void take_block(void (^block)()) { block(); }
// ARC: %[[CAPTURE1:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %[[BLOCK]], i32 0, i32 5
// ARC: store i32 %{{.*}}, i32* %[[CAPTURE1]]
+// ARC-LABEL: define internal void @"_ZZ10-[Foo foo]ENK3$_4clEv"(
+// ARC-NOT: @objc_storeStrong(
+// ARC: ret void
+
// ARC: define internal void @"___ZZN13LambdaCapture4foo1ERiENK3$_3clEv_block_invoke"
// ARC: %[[CAPTURE2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32 }>* %{{.*}}, i32 0, i32 5
// ARC: store i32 %{{.*}}, i32* %[[CAPTURE2]]
@@ -124,6 +128,15 @@ namespace BlockInLambda {
};
}
+@interface NSObject @end
+@interface Foo : NSObject @end
+@implementation Foo
+- (void)foo {
+ [&] {
+ ^{ (void)self; }();
+ }();
+}
+@end
// ARC: attributes [[NUW]] = { noinline nounwind{{.*}} }
// MRC: attributes [[NUW]] = { noinline nounwind{{.*}} }
diff --git a/test/CodeGenObjCXX/lambda-to-block.mm b/test/CodeGenObjCXX/lambda-to-block.mm
new file mode 100644
index 000000000000..a8d0718b1244
--- /dev/null
+++ b/test/CodeGenObjCXX/lambda-to-block.mm
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -x objective-c++ -fblocks -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -std=c++1z -emit-llvm -o - %s | FileCheck %s
+
+// rdar://31385153
+// Shouldn't crash!
+
+void takesBlock(void (^)(void));
+
+struct Copyable {
+ Copyable(const Copyable &x);
+};
+
+void hasLambda(Copyable x) {
+ takesBlock([x] () { });
+}
+// CHECK-LABEL: define internal void @__copy_helper_block_
+// CHECK: call void @"_ZZ9hasLambda8CopyableEN3$_0C1ERKS0_"
+// CHECK-LABEL: define internal void @"_ZZ9hasLambda8CopyableEN3$_0C2ERKS0_"
+// CHECK: call void @_ZN8CopyableC1ERKS_
diff --git a/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm
index 682add3cb531..6a112312bd88 100644
--- a/test/CodeGenObjCXX/literals.mm
+++ b/test/CodeGenObjCXX/literals.mm
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-arc-exceptions -O2 -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=gnu++98 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-arc-exceptions -O2 -disable-llvm-passes -o - %s | FileCheck %s
#include "literal-support.h"
@@ -21,7 +21,7 @@ void test_array() {
// Initializing first element
// CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]])
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0
// CHECK-NEXT: call void @_ZN1XC1Ev
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
@@ -51,7 +51,7 @@ void test_array() {
// CHECK-NOT: ret void
// CHECK: call void @objc_release
// CHECK-NEXT: [[PTR2:%.*]] = bitcast i8** [[ARR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTR2]])
// CHECK-NEXT: ret void
// Check cleanups
@@ -73,7 +73,7 @@ void test_array_instantiation() {
// Initializing first element
// CHECK: [[PTR1:%.*]] = bitcast i8** [[ARR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTR1]])
// CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[OBJECTS]], i64 0, i64 0
// CHECK-NEXT: call void @_ZN1XC1Ev
// CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv
@@ -103,7 +103,7 @@ void test_array_instantiation() {
// CHECK-NOT: ret void
// CHECK: call void @objc_release
// CHECK-NEXT: [[PTR2]] = bitcast i8** [[ARR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTR2]])
// CHECK-NEXT: ret void
// Check cleanups
diff --git a/test/CodeGenObjCXX/objc-weak.mm b/test/CodeGenObjCXX/objc-weak.mm
new file mode 100644
index 000000000000..68c2d4611146
--- /dev/null
+++ b/test/CodeGenObjCXX/objc-weak.mm
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-weak -fobjc-runtime-has-weak -std=c++11 -o - %s | FileCheck %s
+
+struct A { __weak id x; };
+
+id test0() {
+ A a;
+ A b = a;
+ A c(static_cast<A&&>(b));
+ a = c;
+ c = static_cast<A&&>(a);
+ return c.x;
+}
+
+// Copy Assignment Operator
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.A* @_ZN1AaSERKS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
+
+// Move Assignment Operator
+// CHECK-LABEL: define linkonce_odr dereferenceable({{[0-9]+}}) %struct.A* @_ZN1AaSEOS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[T0]])
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]])
+
+// Default Constructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AC2Ev(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: store i8* null, i8** [[T0]]
+
+// Copy Constructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AC2ERKS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: call void @objc_copyWeak(i8** [[T0]], i8** [[T1]])
+
+// Move Constructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AC2EOS_(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[OBJECTADDR:%.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: [[OBJECT:%.*]] = load [[A]]*, [[A]]** [[OBJECTADDR]]
+// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[OBJECT]], i32 0, i32 0
+// CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
+
+// Destructor
+// CHECK-LABEL: define linkonce_odr void @_ZN1AD2Ev(
+// CHECK: [[THISADDR:%this.*]] = alloca [[A:.*]]*
+// CHECK: [[THIS:%this.*]] = load [[A]]*, [[A]]** [[THISADDR]]
+// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[A]], [[A]]* [[THIS]], i32 0, i32 0
+// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+
diff --git a/test/CodeGenObjCXX/objfw-exceptions.mm b/test/CodeGenObjCXX/objfw-exceptions.mm
new file mode 100644
index 000000000000..2c3182f543ac
--- /dev/null
+++ b/test/CodeGenObjCXX/objfw-exceptions.mm
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -fcxx-exceptions -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-DWARF
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fexceptions -fobjc-exceptions -fobjc-runtime=objfw -fcxx-exceptions -fsjlj-exceptions -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-SJLJ
+
+@interface OCType @end
+void opaque();
+
+// CHECK: define void @_Z3foov()
+// CHECK-DWARF-SAME: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_v0 to i8*)
+// CHECK-SJLJ-SAME: personality i8* bitcast (i32 (...)* @__gnu_objc_personality_sj0 to i8*)
+void foo() {
+try {
+// CHECK: invoke void @_Z6opaquev
+opaque();
+} catch (OCType *T) {
+// CHECK: landingpad { i8*, i32 }
+}
+}