aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenObjC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-16 16:02:28 +0000
commit7442d6faa2719e4e7d33a7021c406c5a4facd74d (patch)
treec72b9241553fc9966179aba84f90f17bfa9235c3 /test/CodeGenObjC
parentb52119637f743680a99710ce5fdb6646da2772af (diff)
downloadsrc-7442d6faa2719e4e7d33a7021c406c5a4facd74d.tar.gz
src-7442d6faa2719e4e7d33a7021c406c5a4facd74d.zip
Vendor import of clang trunk r300422:vendor/clang/clang-trunk-r300422
Notes
Notes: svn path=/vendor/clang/dist/; revision=317019 svn path=/vendor/clang/clang-trunk-r300422/; revision=317020; tag=vendor/clang/clang-trunk-r300422
Diffstat (limited to 'test/CodeGenObjC')
-rw-r--r--test/CodeGenObjC/arc-blocks.m57
-rw-r--r--test/CodeGenObjC/arc-linetable-autorelease.m5
-rw-r--r--test/CodeGenObjC/arc-precise-lifetime.m68
-rw-r--r--test/CodeGenObjC/arc-ternary-op.m12
-rw-r--r--test/CodeGenObjC/arc.m126
-rw-r--r--test/CodeGenObjC/availability-cf-link-guard.m45
-rw-r--r--test/CodeGenObjC/availability-check.m31
-rw-r--r--test/CodeGenObjC/empty-collection-literals.m51
-rw-r--r--test/CodeGenObjC/exceptions.m4
-rw-r--r--test/CodeGenObjC/ivar-type-encoding.m35
-rw-r--r--test/CodeGenObjC/ubsan-bool.m57
-rw-r--r--test/CodeGenObjC/ubsan-nonnull-and-nullability.m31
-rw-r--r--test/CodeGenObjC/ubsan-nonnull.m48
-rw-r--r--test/CodeGenObjC/ubsan-nullability.m182
14 files changed, 632 insertions, 120 deletions
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
index f67136b7b226..4bb618c3a415 100644
--- a/test/CodeGenObjC/arc-blocks.m
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -75,7 +75,7 @@ void test3(void (^sink)(id*)) {
// CHECK-NEXT: bitcast i8*
// CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
// CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[STRONGPTR1]])
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
@@ -97,7 +97,7 @@ void test3(void (^sink)(id*)) {
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[STRONG]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[STRONGPTR2]])
// CHECK-NEXT: load void (i8**)*, void (i8**)** [[SINK]]
// CHECK-NEXT: bitcast
@@ -172,7 +172,7 @@ void test5(void) {
// CHECK: [[VAR:%.*]] = alloca i8*
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast i8** [[VAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[VARPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[VARPTR1]])
// CHECK: [[T0:%.*]] = call i8* @test5_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
@@ -185,7 +185,7 @@ void test5(void) {
// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK: call void @test5_helper
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast i8** [[VAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[VARPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[VARPTR2]])
// CHECK-NEXT: ret void
}
@@ -199,7 +199,7 @@ void test6(void) {
// CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 48, i8* [[VARPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 48, i8* [[VARPTR1]])
// CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 2
// 0x02000000 - has copy/dispose helpers weak
// CHECK-NEXT: store i32 1107296256, i32* [[T0]]
@@ -218,7 +218,7 @@ void test6(void) {
// CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
// CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 48, i8* [[VARPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 48, i8* [[VARPTR2]])
// CHECK-NEXT: ret void
// CHECK-LABEL: define internal void @__Block_byref_object_copy_.{{[0-9]+}}(i8*, i8*) #{{[0-9]+}} {
@@ -506,7 +506,7 @@ void test13(id x) {
// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
// CHECK-NEXT: [[BPTR1:%.*]] = bitcast void ()** [[B]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[BPTR1]])
// CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]], align 8
// CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
@@ -532,8 +532,6 @@ void test13(id x) {
// CHECK-NEXT: [[T0:%.*]] = load void ()*, void ()** [[B]]
// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // CHECK-NEXT: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[BPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]]
// CHECK-NEXT: br i1 [[T0]]
@@ -541,7 +539,9 @@ void test13(id x) {
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: br label
- // CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
+ // CHECK: [[BPTR2:%.*]] = bitcast void ()** [[B]] to i8*
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[BPTR2]])
+ // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: ret void
}
@@ -566,7 +566,7 @@ void test16() {
// CHECK: [[BLKVAR:%.*]] = alloca void ()*, align 8
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK-NEXT: [[BLKVARPTR1:%.*]] = bitcast void ()** [[BLKVAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[BLKVARPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[BLKVARPTR1]])
// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-NEXT: store void ()* null, void ()** [[BLKVAR]], align 8
}
@@ -667,6 +667,41 @@ void test18(id x) {
// CHECK-UNOPT-NEXT: ret void
}
+// Ensure that we don't emit helper code in copy/dispose routines for variables
+// that are const-captured.
+void testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers(id x, id y) {
+ id __unsafe_unretained unsafeObject = x;
+ (^ { testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers(x, unsafeObject); })();
+}
+
+// CHECK-LABEL: testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers_block_invoke
+// CHECK-UNOPT-LABEL: testUnsafeUnretainedLifetimeInCopyAndDestroyHelpers_block_invoke
+
+// CHECK-UNOPT: @__copy_helper_block
+// CHECK-UNOPT: alloca
+// CHECK-UNOPT-NEXT: alloca
+// CHECK-UNOPT-NEXT: store
+// CHECK-UNOPT-NEXT: store
+// CHECK-UNOPT-NEXT: load
+// CHECK-UNOPT-NEXT: bitcast
+// CHECK-UNOPT-NEXT: load
+// CHECK-UNOPT-NEXT: bitcast
+// CHECK-UNOPT-NEXT: getelementptr
+// CHECK-UNOPT-NEXT: getelementptr
+// CHECK-UNOPT-NEXT: load
+// CHECK-UNOPT-NEXT: store
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong
+// CHECK-UNOPT-NEXT: ret
+
+// CHECK-UNOPT: @__destroy_helper_block
+// CHECK-UNOPT: alloca
+// CHECK-UNOPT-NEXT: store
+// CHECK-UNOPT-NEXT: load
+// CHECK-UNOPT-NEXT: bitcast
+// CHECK-UNOPT-NEXT: getelementptr
+// CHECK-UNOPT-NEXT: call void @objc_storeStrong
+// CHECK-UNOPT-NEXT: ret
+
// rdar://13588325
void test19_sink(void (^)(int));
void test19(void (^b)(void)) {
diff --git a/test/CodeGenObjC/arc-linetable-autorelease.m b/test/CodeGenObjC/arc-linetable-autorelease.m
index 26a779b8d6db..6812e8a6de83 100644
--- a/test/CodeGenObjC/arc-linetable-autorelease.m
+++ b/test/CodeGenObjC/arc-linetable-autorelease.m
@@ -30,11 +30,10 @@ NSRect NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h);
// CHECK: define {{.*}}_createBezierPathWithWidth
// CHECK: load {{.*}} %path, align {{.*}}, !dbg ![[RET:[0-9]+]]
// CHECK: call void @objc_storeStrong{{.*}} !dbg ![[ARC:[0-9]+]]
- // CHECK: call {{.*}} @objc_autoreleaseReturnValue{{.*}} !dbg ![[ARC1:[0-9]+]]
+ // CHECK: call {{.*}} @objc_autoreleaseReturnValue{{.*}} !dbg ![[ARC]]
// CHECK: ret {{.*}} !dbg ![[ARC]]
// CHECK: ![[RET]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
return path;
- // CHECK: ![[ARC]] = !DILocation(line: [[@LINE+2]], scope: !{{.*}})
- // CHECK: ![[ARC1]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
+ // CHECK: ![[ARC]] = !DILocation(line: [[@LINE+1]], scope: !{{.*}})
}
@end
diff --git a/test/CodeGenObjC/arc-precise-lifetime.m b/test/CodeGenObjC/arc-precise-lifetime.m
index eb3111c68a5a..a366c08bbbf6 100644
--- a/test/CodeGenObjC/arc-precise-lifetime.m
+++ b/test/CodeGenObjC/arc-precise-lifetime.m
@@ -8,7 +8,7 @@ void test0() {
x = 0;
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: [[CALL:%.*]] = call i8* @test0_helper()
// CHECK-NEXT: store i8* [[CALL]], i8** [[X]]
@@ -22,7 +22,7 @@ void test0() {
// CHECK-NOT: clang.imprecise_release
// 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
}
@@ -40,14 +40,14 @@ void test1a_message(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -57,12 +57,12 @@ void test1a_message(void) {
// CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T6]], i8**
// CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
Test1 *ptr = test1_helper();
char *c = [(ptr) interior];
@@ -74,14 +74,14 @@ void test1a_property(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -91,12 +91,12 @@ void test1a_property(void) {
// CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T6]], i8**
// CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
Test1 *ptr = test1_helper();
char *c = ptr.interior;
@@ -108,27 +108,27 @@ void test1b_message(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T3]], i8**
// CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
PRECISE_LIFETIME Test1 *ptr = test1_helper();
char *c = [ptr interior];
@@ -139,27 +139,27 @@ void test1b_property(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[C:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[CPTR1:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T3:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T3]], i8**
// CHECK-NEXT: [[CPTR2:%.*]] = bitcast i8** [[C]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
// CHECK-NOT: clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
PRECISE_LIFETIME Test1 *ptr = test1_helper();
char *c = ptr.interior;
@@ -170,14 +170,14 @@ void test1c_message(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -187,12 +187,12 @@ void test1c_message(void) {
// CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T6]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
Test1 *ptr = test1_helper();
char *pc = [ptr PropertyReturnsInnerPointer];
@@ -203,14 +203,14 @@ void test1c_property(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
@@ -220,12 +220,12 @@ void test1c_property(void) {
// CHECK-NEXT: [[T6:%.*]] = call i8* bitcast
// CHECK-NEXT: store i8* [[T6]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
Test1 *ptr = test1_helper();
char *pc = ptr.PropertyReturnsInnerPointer;
@@ -236,26 +236,26 @@ void test1d_message(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
// CHECK-NEXT: store i8* [[CALL1]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[TEN]])
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
PRECISE_LIFETIME Test1 *ptr = test1_helper();
char *pc = [ptr PropertyReturnsInnerPointer];
@@ -266,26 +266,26 @@ void test1d_property(void) {
// CHECK: [[PTR:%.*]] = alloca [[PTR_T:%.*]]*, align 8
// CHECK: [[PC:%.*]] = alloca i8*, align 8
// CHECK: [[PTRPTR1:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 8, i8* [[PTRPTR1]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PTRPTR1]])
// CHECK: [[T0:%.*]] = call [[TEST1:%.*]]* @test1_helper()
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[TEST1]]*
// CHECK-NEXT: store [[TEST1]]* [[T3]]
// CHECK-NEXT: [[PCPTR1:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[PCPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[PCPTR1]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[SEVEN:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
// CHECK-NEXT: [[EIGHT:%.*]] = bitcast [[TEST1]]* [[T0]] to i8*
// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[EIGHT]], i8* [[SEVEN]])
// CHECK-NEXT: store i8* [[CALL1]], i8**
// CHECK-NEXT: [[PCPTR2:%.*]] = bitcast i8** [[PC]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PCPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PCPTR2]])
// CHECK-NEXT: [[NINE:%.*]] = load [[TEST1]]*, [[TEST1]]**
// CHECK-NEXT: [[TEN:%.*]] = bitcast [[TEST1]]* [[NINE]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[TEN]])
// CHECK-NEXT: [[PTRPTR2:%.*]] = bitcast [[PTR_T]]** [[PTR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTRPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[PTRPTR2]])
// CHECK-NEXT: ret void
PRECISE_LIFETIME Test1 *ptr = test1_helper();
char *pc = ptr.PropertyReturnsInnerPointer;
diff --git a/test/CodeGenObjC/arc-ternary-op.m b/test/CodeGenObjC/arc-ternary-op.m
index 883fcd366622..3488d2c5387a 100644
--- a/test/CodeGenObjC/arc-ternary-op.m
+++ b/test/CodeGenObjC/arc-ternary-op.m
@@ -11,7 +11,7 @@ void test0(_Bool cond) {
// CHECK-NEXT: zext
// CHECK-NEXT: store
// CHECK-NEXT: [[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-NEXT: [[T0:%.*]] = load i8, i8* [[COND]]
// CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1
// CHECK-NEXT: store i1 false, i1* [[RELCOND]]
@@ -32,7 +32,7 @@ void test0(_Bool cond) {
// CHECK: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
// 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
id x = (cond ? 0 : test0_helper());
}
@@ -54,10 +54,10 @@ void test1(int cond) {
// CHECK-NEXT: [[CONDCLEANUP:%.*]] = alloca i1
// CHECK-NEXT: store i32
// CHECK-NEXT: [[STRONGPTR1:%.*]] = bitcast i8** [[STRONG]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[STRONGPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[STRONGPTR1]])
// CHECK-NEXT: store i8* null, i8** [[STRONG]]
// CHECK-NEXT: [[WEAKPTR1:%.*]] = bitcast i8** [[WEAK]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[WEAKPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[WEAKPTR1]])
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null)
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[COND]]
@@ -102,9 +102,9 @@ void test1(int cond) {
// CHECK: call void @objc_destroyWeak(i8** [[WEAK]])
// CHECK: [[WEAKPTR2:%.*]] = bitcast i8** [[WEAK]] to i8*
- // CHECK: call void @llvm.lifetime.end(i64 8, i8* [[WEAKPTR2]])
+ // CHECK: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[WEAKPTR2]])
// CHECK: [[STRONGPTR2:%.*]] = bitcast i8** [[STRONG]] to i8*
- // CHECK: call void @llvm.lifetime.end(i64 8, i8* [[STRONGPTR2]])
+ // CHECK: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[STRONGPTR2]])
// CHECK: ret void
}
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index 87cf667b4e5e..d34156ee3473 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -1,36 +1,36 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-passes -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-GLOBALS %s
// rdar://13129783. Check both native/non-native arc platforms. Here we check
// that they treat nonlazybind differently.
-// RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s
-// RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.6.0 -triple x86_64-apple-darwin10 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-ALIEN %s
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.7.0 -triple x86_64-apple-darwin11 -Wno-objc-root-class -Wno-incompatible-pointer-types -Wno-arc-unsafe-retained-assign -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=ARC-NATIVE %s
// ARC-ALIEN: declare extern_weak void @objc_storeStrong(i8**, i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8*)
+// ARC-ALIEN: declare extern_weak i8* @objc_retain(i8* returned)
+// ARC-ALIEN: declare extern_weak i8* @objc_autoreleaseReturnValue(i8* returned)
// ARC-ALIEN: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB:#[0-9]+]]
// ARC-ALIEN: declare extern_weak void @objc_release(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8*)
+// ARC-ALIEN: declare extern_weak i8* @objc_retainAutoreleasedReturnValue(i8* returned)
// ARC-ALIEN: declare extern_weak i8* @objc_initWeak(i8**, i8*)
// ARC-ALIEN: declare extern_weak i8* @objc_storeWeak(i8**, i8*)
// ARC-ALIEN: declare extern_weak i8* @objc_loadWeakRetained(i8**)
// ARC-ALIEN: declare extern_weak void @objc_destroyWeak(i8**)
-// ARC-ALIEN: declare extern_weak i8* @objc_autorelease(i8*)
-// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8*)
+// declare extern_weak i8* @objc_autorelease(i8*)
+// ARC-ALIEN: declare extern_weak i8* @objc_retainAutorelease(i8* returned)
// ARC-NATIVE: declare void @objc_storeStrong(i8**, i8*)
-// ARC-NATIVE: declare i8* @objc_retain(i8*) [[NLB:#[0-9]+]]
-// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8*)
+// ARC-NATIVE: declare i8* @objc_retain(i8* returned) [[NLB:#[0-9]+]]
+// ARC-NATIVE: declare i8* @objc_autoreleaseReturnValue(i8* returned)
// ARC-NATIVE: declare i8* @objc_msgSend(i8*, i8*, ...) [[NLB]]
// ARC-NATIVE: declare void @objc_release(i8*) [[NLB]]
-// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+// ARC-NATIVE: declare i8* @objc_retainAutoreleasedReturnValue(i8* returned)
// ARC-NATIVE: declare i8* @objc_initWeak(i8**, i8*)
// ARC-NATIVE: declare i8* @objc_storeWeak(i8**, i8*)
// ARC-NATIVE: declare i8* @objc_loadWeakRetained(i8**)
// ARC-NATIVE: declare void @objc_destroyWeak(i8**)
-// ARC-NATIVE: declare i8* @objc_autorelease(i8*)
-// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8*)
+// declare i8* @objc_autorelease(i8*)
+// ARC-NATIVE: declare i8* @objc_retainAutorelease(i8* returned)
// CHECK-LABEL: define void @test0
void test0(id x) {
@@ -49,14 +49,14 @@ id test1(id x) {
// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: store i8* null, i8** [[Y]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T0]])
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
// CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RET]])
@@ -102,7 +102,7 @@ void test3_unelided() {
// CHECK: [[X:%.*]] = alloca [[TEST3:%.*]]*
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST3]]** [[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-NEXT: store [[TEST3]]* null, [[TEST3]]** [[X]], align
Test3 *x;
@@ -127,7 +127,7 @@ void test3_unelided() {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST3]]** [[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
}
@@ -135,7 +135,7 @@ void test3_unelided() {
void test3() {
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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]])
id x = [[Test3 alloc] initWith: 5];
@@ -171,7 +171,7 @@ void test3() {
// CHECK-NEXT: [[TMP:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[TMP]]) [[NUW]]
// 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
}
@@ -254,13 +254,13 @@ id test6_helper(void) __attribute__((ns_returns_retained));
void test6() {
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: [[CALL:%.*]] = call i8* @test6_helper()
// CHECK-NEXT: store i8* [[CALL]], i8** [[X]]
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// 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
id x = test6_helper();
}
@@ -270,7 +270,7 @@ void test7_helper(id __attribute__((ns_consumed)));
void test7() {
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: store i8* null, i8** [[X]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) [[NUW]]
@@ -278,7 +278,7 @@ void test7() {
// CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) [[NUW]], !clang.imprecise_release
// 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
id x;
test7_helper(x);
@@ -289,12 +289,12 @@ void test8() {
__unsafe_unretained id x = test8_helper();
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: [[T0:%.*]] = call i8* @test8_helper()
// CHECK-NEXT: store i8* [[T0]], i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]], !clang.imprecise_release
// 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
}
@@ -309,10 +309,10 @@ void test10() {
// CHECK: [[X:%.*]] = alloca [[TEST10:%.*]]*, align
// CHECK-NEXT: [[Y:%.*]] = alloca i8*, align
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast [[TEST10]]** [[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-NEXT: store [[TEST10]]* null, [[TEST10]]** [[X]]
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: load [[TEST10]]*, [[TEST10]]** [[X]], align
// CHECK-NEXT: load i8*, i8** @OBJC_SELECTOR_REFERENCES_{{[0-9]*}}
// CHECK-NEXT: bitcast
@@ -333,12 +333,12 @@ void test10() {
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])
+ // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: [[T0:%.*]] = load [[TEST10]]*, [[TEST10]]** [[X]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST10]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast [[TEST10]]** [[X]] to i8*
- // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
+ // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
}
@@ -348,14 +348,14 @@ void test11(id (*f)(void) __attribute__((ns_returns_retained))) {
// CHECK-NEXT: [[X:%.*]] = alloca i8*, align
// CHECK-NEXT: store i8* ()* {{%.*}}, i8* ()** [[F]], align
// CHECK-NEXT: [[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-NEXT: [[T0:%.*]] = load i8* ()*, i8* ()** [[F]], align
// CHECK-NEXT: [[T1:%.*]] = call i8* [[T0]]()
// CHECK-NEXT: store i8* [[T1]], i8** [[X]], align
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T3]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
- // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
+ // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
id x = f();
}
@@ -369,7 +369,7 @@ void test12(void) {
__weak id x = test12_helper();
// CHECK-NEXT: [[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-NEXT: [[T0:%.*]] = call i8* @test12_helper()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T1]])
@@ -383,17 +383,17 @@ void test12(void) {
id y = x;
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_loadWeakRetained(i8** [[X]])
// CHECK-NEXT: store i8* [[T2]], i8** [[Y]], align
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]], !clang.imprecise_release
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])
+ // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
- // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
+ // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK: ret void
}
@@ -402,7 +402,7 @@ void test13(void) {
// CHECK-LABEL: define void @test13()
// CHECK: [[X:%.*]] = alloca i8*, align
// CHECK-NEXT: [[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-NEXT: store i8* null, i8** [[X]], align
id x;
@@ -429,7 +429,7 @@ void test13(void) {
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]]) [[NUW]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8*
- // CHECK-NEXT: void @llvm.lifetime.end(i64 8, i8* [[XPTR2]])
+ // CHECK-NEXT: void @llvm.lifetime.end.p0i8(i64 8, i8* [[XPTR2]])
// CHECK-NEXT: ret void
}
@@ -1005,7 +1005,7 @@ void test37(void) {
// CHECK: [[VAR:%.*]] = alloca [[TEST37:%.*]]*,
// CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[VARPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[VARPTR1]])
// CHECK-NEXT: store [[TEST37]]* null, [[TEST37]]** [[VAR]]
// CHECK-NEXT: [[W0:%.*]] = load [[TEST37]]*, [[TEST37]]** [[VAR]]
@@ -1027,7 +1027,7 @@ void test37(void) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST37]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
// CHECK-NEXT: [[VARPTR2:%.*]] = bitcast [[TEST37]]** [[VAR]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[VARPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[VARPTR2]])
// CHECK-NEXT: ret void
}
@@ -1085,7 +1085,7 @@ void test47(void) {
// CHECK-LABEL: define void @test47()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: store i8* null, i8** [[X]]
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test47_helper()
// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])
@@ -1099,7 +1099,7 @@ void test47(void) {
// CHECK-NEXT: [[T4:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T4]])
// 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
}
@@ -1109,7 +1109,7 @@ void test48(void) {
// CHECK-LABEL: define void @test48()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: [[T0:%.*]] = call i8* @objc_initWeak(i8** [[X]], i8* null)
// CHECK-NEXT: [[T1:%.*]] = call i8* @test48_helper()
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]])
@@ -1118,7 +1118,7 @@ void test48(void) {
// CHECK-NEXT: call void @objc_release(i8* [[T2]])
// CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]])
// 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
}
@@ -1128,7 +1128,7 @@ void test49(void) {
// CHECK-LABEL: define void @test49()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[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-NEXT: store i8* null, i8** [[X]]
// CHECK-NEXT: [[CALL:%.*]] = call i8* @test49_helper()
// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[CALL]])
@@ -1137,7 +1137,7 @@ void test49(void) {
// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainAutorelease(i8* [[T1]])
// CHECK-NEXT: store i8* [[T3]], i8** [[X]]
// 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
}
@@ -1174,13 +1174,13 @@ id test52(void) {
// CHECK: [[X:%.*]] = alloca i32
// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*
// CHECK-NEXT: [[XPTR1:%.*]] = bitcast i32* [[X]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[XPTR1]])
+// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[XPTR1]])
// CHECK-NEXT: store i32 5, i32* [[X]],
// CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[X]],
// CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[TMPALLOCA]]
// CHECK-NEXT: [[XPTR2:%.*]] = bitcast i32* [[X]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[XPTR2]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[XPTR2]])
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[TMPALLOCA]]
// CHECK-NEXT: [[T3:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T2]])
// CHECK-NEXT: ret i8* [[T3]]
@@ -1196,9 +1196,9 @@ void test53(void) {
// CHECK-NEXT: [[Y:%.*]] = alloca i8*,
// CHECK-NEXT: [[TMPALLOCA:%.*]] = alloca i8*,
// CHECK-NEXT: [[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-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
+// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test53_helper()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]],
@@ -1208,14 +1208,14 @@ void test53(void) {
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T2]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: [[T3:%.*]] = load i8*, i8** [[TMPALLOCA]]
// CHECK-NEXT: store i8* [[T3]], i8** [[X]],
// CHECK-NEXT: load i8*, i8** [[X]],
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// 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
}
@@ -1263,13 +1263,13 @@ void test56_test(void) {
// CHECK-LABEL: define void @test56_test()
// CHECK: [[X:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[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: [[T0:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(
// CHECK-NEXT: store i8* [[T0]], i8** [[X]]
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// 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
}
@@ -1350,7 +1350,7 @@ void test61(void) {
[test61_make() performSelector: @selector(test61_void)];
// CHECK-NEXT: [[YPTR1:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[YPTR1]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[YPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test61_make()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES_
@@ -1364,7 +1364,7 @@ void test61(void) {
// CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: [[YPTR2:%.*]] = bitcast i8** [[Y]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[YPTR2]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[YPTR2]])
// CHECK-NEXT: ret void
}
@@ -1378,7 +1378,7 @@ void test62(void) {
extern void test62_body(void);
// CHECK-NEXT: [[IPTR:%.*]] = bitcast i32* [[I]] to i8*
- // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR]])
+ // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* [[IPTR]])
// CHECK-NEXT: store i32 0, i32* [[I]], align 4
// CHECK-NEXT: br label
@@ -1471,11 +1471,11 @@ void test67(void) {
// CHECK-LABEL: define void @test67()
// CHECK: [[CL:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CLPTR1]])
+// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CLPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()
// CHECK-NEXT: store i8* [[T0]], i8** [[CL]], align 8
// CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CLPTR2]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CLPTR2]])
// CHECK-NEXT: ret void
Class test68_helper(void);
@@ -1485,14 +1485,14 @@ void test68(void) {
// CHECK-LABEL: define void @test68()
// CHECK: [[CL:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[CLPTR1:%.*]] = bitcast i8** [[CL]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[CLPTR1]])
+// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CLPTR1]])
// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[CL]], align 8
// CHECK-NEXT: [[T2:%.*]] = load i8*, i8** [[CL]]
// CHECK-NEXT: call void @objc_release(i8* [[T2]])
// CHECK-NEXT: [[CLPTR2:%.*]] = bitcast i8** [[CL]] to i8*
-// CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[CLPTR2]])
+// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CLPTR2]])
// CHECK-NEXT: ret void
// rdar://problem/10564852
@@ -1504,7 +1504,9 @@ void test68(void) {
// CHECK: [[SELF:%.*]] = alloca [[TEST69:%.*]]*, align 8
// CHECK: [[T0:%.*]] = load [[TEST69]]*, [[TEST69]]** [[SELF]], align 8
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8*
-// CHECK-NEXT: ret i8* [[T1]]
+// CHECK-NEXT: [[RETAIN:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[AUTORELEASE:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RETAIN]])
+// CHECK-NEXT: ret i8* [[AUTORELEASE]]
// rdar://problem/10907547
void test70(id i) {
diff --git a/test/CodeGenObjC/availability-cf-link-guard.m b/test/CodeGenObjC/availability-cf-link-guard.m
new file mode 100644
index 000000000000..918d13ffd9f4
--- /dev/null
+++ b/test/CodeGenObjC/availability-cf-link-guard.m
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11 -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK,CHECK_LINK_OPT %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11 -emit-llvm -o - -D USE_BUILTIN %s | FileCheck --check-prefixes=CHECK,CHECK_LINK_OPT %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11 -emit-llvm -o - -D DEF_CF %s | FileCheck --check-prefixes=CHECK_CF,CHECK_LINK_OPT %s
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK_NO_GUARD %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux -emit-llvm -o - %s | FileCheck --check-prefix=CHECK_NO_GUARD %s
+
+#ifdef DEF_CF
+struct CFBundle;
+typedef struct CFBundle *CFBundleRef;
+unsigned CFBundleGetVersionNumber(CFBundleRef bundle);
+// CHECK_CF: declare i32 @CFBundleGetVersionNumber(%struct.CFBundle*)
+// CHECK_CF: @__clang_at_available_requires_core_foundation_framework
+// CHECK_CF-NEXT: call {{.*}}@CFBundleGetVersionNumber
+#endif
+
+void use_at_available() {
+#ifdef DEF_CF
+ CFBundleGetVersionNumber(0);
+#endif
+#ifdef USE_BUILTIN
+ if (__builtin_available(macos 10.12, *))
+ ;
+#else
+ if (@available(macos 10.12, *))
+ ;
+#endif
+}
+
+// CHECK: @llvm.compiler.used{{.*}}@__clang_at_available_requires_core_foundation_framework
+
+// CHECK: declare i32 @CFBundleGetVersionNumber(i8*)
+
+// CHECK-LABEL: linkonce hidden void @__clang_at_available_requires_core_foundation_framework
+// CHECK: call i32 @CFBundleGetVersionNumber(i8* null)
+// CHECK-NEXT: unreachable
+
+// CHECK_NO_GUARD-NOT: __clang_at_available_requires_core_foundation_framework
+// CHECK_NO_GUARD-NOT: CFBundleGetVersionNumber
+
+// CHECK_LINK_OPT: !"Linker Options", ![[OPTS:[0-9]+]]
+// CHECK_LINK_OPT: ![[OPTS]] = !{![[FRAMEWORK:[0-9]+]]
+// CHECK_LINK_OPT: ![[FRAMEWORK]] = !{!"-framework", !"CoreFoundation"}
+
+// CHECK_NO_GUARD-NOT: "Linker Options"
+// CHECK_NO_GUARD-NOT: CoreFoundation
diff --git a/test/CodeGenObjC/availability-check.m b/test/CodeGenObjC/availability-check.m
new file mode 100644
index 000000000000..71c5ff77c96a
--- /dev/null
+++ b/test/CodeGenObjC/availability-check.m
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11 -emit-llvm -o - %s | FileCheck %s
+
+void use_at_available() {
+ // CHECK: call i32 @__isOSVersionAtLeast(i32 10, i32 12, i32 0)
+ // CHECK-NEXT: icmp ne
+ if (__builtin_available(macos 10.12, *))
+ ;
+
+ // CHECK: call i32 @__isOSVersionAtLeast(i32 10, i32 12, i32 0)
+ // CHECK-NEXT: icmp ne
+ if (@available(macos 10.12, *))
+ ;
+
+ // CHECK: call i32 @__isOSVersionAtLeast(i32 10, i32 12, i32 42)
+ // CHECK-NEXT: icmp ne
+ if (__builtin_available(ios 10, macos 10.12.42, *))
+ ;
+
+ // CHECK-NOT: call i32 @__isOSVersionAtLeast
+ // CHECK: br i1 true
+ if (__builtin_available(ios 10, *))
+ ;
+
+ // This check should be folded: our deployment target is 10.11.
+ // CHECK-NOT: call i32 @__isOSVersionAtLeast
+ // CHECK: br i1 true
+ if (__builtin_available(macos 10.11, *))
+ ;
+}
+
+// CHECK: declare i32 @__isOSVersionAtLeast(i32, i32, i32)
diff --git a/test/CodeGenObjC/empty-collection-literals.m b/test/CodeGenObjC/empty-collection-literals.m
new file mode 100644
index 000000000000..0f9715f521f3
--- /dev/null
+++ b/test/CodeGenObjC/empty-collection-literals.m
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx10.10.0 -fobjc-runtime=macosx-10.10.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-macosx10.11.0 -fobjc-runtime=macosx-10.11.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-ios8.0 -fobjc-runtime=ios-8.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-ios9.0 -fobjc-runtime=ios-9.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+// RUN: %clang_cc1 -I %S/Inputs -triple armv7k-apple-watchos2.0 -fobjc-runtime=watchos-1.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple armv7k-apple-watchos2.0 -fobjc-runtime=watchos-2.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-tvos8.0 -fobjc-runtime=ios-8.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITHOUT-EMPTY-COLLECTIONS %s
+// RUN: %clang_cc1 -I %S/Inputs -triple arm64-apple-tvos9.0 -fobjc-runtime=ios-9.0 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck -check-prefix=CHECK-WITH-EMPTY-COLLECTIONS %s
+
+#include "literal-support.h"
+
+void test_empty_array() {
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
+
+ // CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_array
+ // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSArray0__
+ // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
+ // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
+ // CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
+ NSArray *arr = @[];
+}
+
+void test_empty_dictionary() {
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_msgSend}}
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: {{call.*objc_retainAutoreleasedReturnValue}}
+ // CHECK-WITHOUT-EMPTY-COLLECTIONS: ret void
+
+ // CHECK-WITH-EMPTY-COLLECTIONS-LABEL: define void @test_empty_dictionary
+ // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITH-EMPTY-COLLECTIONS: load {{.*}} @__NSDictionary0__
+ // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITH-EMPTY-COLLECTIONS: {{call.*objc_retain\(}}
+ // CHECK-WITH-EMPTY-COLLECTIONS-NOT: ret void
+ // CHECK-WITH-EMPTY-COLLECTIONS: call void @objc_storeStrong
+ // CHECK-WITH-EMPTY-COLLECTIONS-NEXT: ret void
+ NSDictionary *dict = @{};
+}
diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m
index 28515c54f32f..439b9401485f 100644
--- a/test/CodeGenObjC/exceptions.m
+++ b/test/CodeGenObjC/exceptions.m
@@ -83,7 +83,7 @@ void f3() {
// CHECK: [[X:%.*]] = alloca i32
// CHECK: [[XPTR:%.*]] = bitcast i32* [[X]] to i8*
- // CHECK: call void @llvm.lifetime.start(i64 4, i8* nonnull [[XPTR]])
+ // CHECK: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[XPTR]])
// CHECK: store i32 0, i32* [[X]]
int x = 0;
@@ -124,7 +124,7 @@ void f3() {
}
// CHECK: call void @f3_helper(i32 4, i32* nonnull [[X]])
- // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* nonnull [[XPTR]])
+ // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[XPTR]])
// CHECK-NEXT: ret void
f3_helper(4, &x);
}
diff --git a/test/CodeGenObjC/ivar-type-encoding.m b/test/CodeGenObjC/ivar-type-encoding.m
new file mode 100644
index 000000000000..ffa5e0d7af0d
--- /dev/null
+++ b/test/CodeGenObjC/ivar-type-encoding.m
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -S -emit-llvm -fobjc-runtime=gcc -o - %s | FileCheck %s
+
+@protocol NSCopying
+@end
+
+@interface NSObject {
+ struct objc_object *isa;
+}
++ (id) new;
+- (id) init;
+@end
+
+@interface NSString : NSObject <NSCopying>
++ (NSString *)foo;
+@end
+
+@interface TestClass : NSObject {
+@public
+ NSString *_stringIvar;
+ int _intIvar;
+}
+@end
+@implementation TestClass
+
+@end
+
+int main() {
+ TestClass *c = [TestClass new];
+ return 0;
+}
+
+// CHECK: @0 = private unnamed_addr constant [12 x i8] c"_stringIvar\00"
+// CHECK: @1 = private unnamed_addr constant [12 x i8] c"@\22NSString\22\00"
+// CHECK: @2 = private unnamed_addr constant [9 x i8] c"_intIvar\00"
+// CHECK: @3 = private unnamed_addr constant [2 x i8] c"i\00"
diff --git a/test/CodeGenObjC/ubsan-bool.m b/test/CodeGenObjC/ubsan-bool.m
index 6d6c08358d07..b30562c4d423 100644
--- a/test/CodeGenObjC/ubsan-bool.m
+++ b/test/CodeGenObjC/ubsan-bool.m
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - | FileCheck %s -check-prefixes=SHARED,OBJC
-// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - | FileCheck %s -check-prefixes=SHARED,OBJC
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - -w | FileCheck %s -check-prefixes=SHARED,OBJC
+// RUN: %clang_cc1 -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - -w | FileCheck %s -check-prefixes=SHARED,OBJC
// RUN: %clang_cc1 -x c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=bool %s -o - | FileCheck %s -check-prefixes=SHARED,C
typedef signed char BOOL;
@@ -10,4 +10,57 @@ BOOL f1() {
// C-NOT: call void @__ubsan_handle_load_invalid_value
BOOL a = 2;
return a + 1;
+ // SHARED: ret i8
}
+
+struct S1 {
+ BOOL b1 : 1;
+};
+
+// SHARED-LABEL: f2
+BOOL f2(struct S1 *s) {
+ // OBJC: [[LOAD:%.*]] = load i8, i8* {{.*}}
+ // OBJC: [[SHL:%.*]] = shl i8 [[LOAD]], 7
+ // OBJC: [[ASHR:%.*]] = ashr i8 [[SHL]], 7
+ // OBJC: icmp ule i8 [[ASHR]], 1, !nosanitize
+ // OBJC: call void @__ubsan_handle_load_invalid_value
+
+ // C-NOT: call void @__ubsan_handle_load_invalid_value
+ return s->b1;
+ // SHARED: ret i8
+}
+
+#ifdef __OBJC__
+@interface I1 {
+@public
+ BOOL b1 : 1;
+}
+@property (nonatomic) BOOL b1;
+@end
+@implementation I1
+@synthesize b1;
+@end
+
+// Check the synthesized getter.
+// OBJC-LABEL: define internal signext i8 @"\01-[I1 b1]"
+// OBJC: [[IVAR:%.*]] = load i64, i64* @"OBJC_IVAR_$_I1.b1"
+// OBJC: [[ADDR:%.*]] = getelementptr inbounds i8, i8* {{.*}}, i64 [[IVAR]]
+// OBJC: [[LOAD:%.*]] = load i8, i8* {{.*}}
+// OBJC: [[SHL:%.*]] = shl i8 [[LOAD]], 7
+// OBJC: [[ASHR:%.*]] = ashr i8 [[SHL]], 7
+// OBJC: icmp ule i8 [[ASHR]], 1, !nosanitize
+// OBJC: call void @__ubsan_handle_load_invalid_value
+
+// Also check direct accesses to the ivar.
+// OBJC-LABEL: f3
+BOOL f3(I1 *i) {
+ // OBJC: [[LOAD:%.*]] = load i8, i8* {{.*}}
+ // OBJC: [[SHL:%.*]] = shl i8 [[LOAD]], 7
+ // OBJC: [[ASHR:%.*]] = ashr i8 [[SHL]], 7
+ // OBJC: icmp ule i8 [[ASHR]], 1, !nosanitize
+ // OBJC: call void @__ubsan_handle_load_invalid_value
+
+ return i->b1;
+ // OBJC: ret i8
+}
+#endif /* __OBJC__ */
diff --git a/test/CodeGenObjC/ubsan-nonnull-and-nullability.m b/test/CodeGenObjC/ubsan-nonnull-and-nullability.m
new file mode 100644
index 000000000000..b927f55cd402
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-nonnull-and-nullability.m
@@ -0,0 +1,31 @@
+// REQUIRES: asserts
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-return,returns-nonnull-attribute,nullability-arg,nonnull-attribute %s -o - -w | FileCheck %s
+
+// If both the annotation and the attribute are present, prefer the attribute,
+// since it actually affects IRGen.
+
+// CHECK-LABEL: define nonnull i32* @f1
+__attribute__((returns_nonnull)) int *_Nonnull f1(int *_Nonnull p) {
+ // CHECK: entry:
+ // CHECK-NEXT: [[ADDR:%.*]] = alloca i32*
+ // CHECK-NEXT: store i32* [[P:%.*]], i32** [[ADDR]]
+ // CHECK-NEXT: [[ARG:%.*]] = load i32*, i32** [[ADDR]]
+ // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* [[ARG]], null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], label %[[CONT:.+]], label %[[HANDLE:[^,]+]]
+ // CHECK: [[HANDLE]]:
+ // CHECK-NEXT: call void @__ubsan_handle_nonnull_return_abort
+ // CHECK-NEXT: unreachable, !nosanitize
+ // CHECK: [[CONT]]:
+ // CHECK-NEXT: ret i32*
+ return p;
+}
+
+// CHECK-LABEL: define void @f2
+void f2(int *_Nonnull __attribute__((nonnull)) p) {}
+
+// CHECK-LABEL: define void @call_f2
+void call_f2() {
+ // CHECK: call void @__ubsan_handle_nonnull_arg_abort
+ // CHECK-NOT: call void @__ubsan_handle_nonnull_arg_abort
+ f2((void *)0);
+}
diff --git a/test/CodeGenObjC/ubsan-nonnull.m b/test/CodeGenObjC/ubsan-nonnull.m
new file mode 100644
index 000000000000..cc0850caf97f
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-nonnull.m
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nonnull-attribute %s -o - -w | FileCheck %s
+
+@interface A
+
+-(void) one_arg: (__attribute__((nonnull)) int *) arg1;
+
+-(void) varargs: (__attribute__((nonnull)) int *) arg1, ...;
+
++(void) clsmethod: (__attribute__((nonnull)) int *) arg1;
+
+@end
+
+@implementation A
+
+// CHECK-LABEL: define internal void @"\01-[A one_arg:]"
+// CHECK-SAME: i32* nonnull
+-(void) one_arg: (__attribute__((nonnull)) int *) arg1 {}
+
+// CHECK-LABEL: define internal void @"\01-[A varargs:]"
+// CHECK-SAME: i32* nonnull
+-(void) varargs: (__attribute__((nonnull)) int *) arg1, ... {}
+
+// CHECK-LABEL: define internal void @"\01+[A clsmethod:]"
+// CHECK-SAME: i32* nonnull
++(void) clsmethod: (__attribute__((nonnull)) int *) arg1 {}
+
+@end
+
+// CHECK-LABEL: define void @call_A
+void call_A(A *a, int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize
+ // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nonnull_arg{{.*}} !nosanitize
+ // CHECK: call void {{.*}} @objc_msgSend {{.*}} ({{.*}}, i32* [[P1]])
+ [a one_arg: p];
+
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize
+ // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nonnull_arg{{.*}} !nosanitize
+ // CHECK: call void {{.*}} @objc_msgSend {{.*}} ({{.*}}, i32* [[P2]], {{.*}})
+ [a varargs: p, p];
+
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P3:%.*]], null, !nosanitize
+ // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nonnull_arg{{.*}} !nosanitize
+ // CHECK: call void {{.*}} @objc_msgSend {{.*}} ({{.*}}, i32* [[P3]])
+ [A clsmethod: p];
+}
diff --git a/test/CodeGenObjC/ubsan-nullability.m b/test/CodeGenObjC/ubsan-nullability.m
new file mode 100644
index 000000000000..457f07136349
--- /dev/null
+++ b/test/CodeGenObjC/ubsan-nullability.m
@@ -0,0 +1,182 @@
+// REQUIRES: asserts
+// RUN: %clang_cc1 -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s
+
+// CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 109, i32 1 {{.*}} i32 100, i32 6
+// CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23
+// CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9
+// CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10
+// CHECK: [[NONNULL_ASSIGN3_LOC:@.*]] = private unnamed_addr global {{.*}} i32 505, i32 10
+// CHECK: [[NONNULL_INIT1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 604, i32 25
+// CHECK: [[NONNULL_INIT2_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 26
+// CHECK: [[NONNULL_INIT2_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 707, i32 29
+// CHECK: [[NONNULL_RV_LOC2:@.*]] = private unnamed_addr global {{.*}} i32 817, i32 1 {{.*}} i32 800, i32 6
+
+#define NULL ((void *)0)
+
+// CHECK-LABEL: define i32* @nonnull_retval1
+#line 100
+int *_Nonnull nonnull_retval1(int *p) {
+ // CHECK: br i1 true, label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
+ // CHECK: [[NULL]]:
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]]
+ return p;
+ // CHECK: [[NONULL]]:
+ // CHECK-NEXT: ret i32*
+}
+
+#line 190
+void nonnull_arg(int *_Nonnull p) {}
+
+// CHECK-LABEL: define void @call_func_with_nonnull_arg
+#line 200
+void call_func_with_nonnull_arg(int *_Nonnull p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]]
+ nonnull_arg(p);
+}
+
+// CHECK-LABEL: define void @nonnull_assign1
+#line 300
+void nonnull_assign1(int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]]
+ int *_Nonnull local;
+ local = p;
+}
+
+// CHECK-LABEL: define void @nonnull_assign2
+#line 400
+void nonnull_assign2(int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]]
+ int *_Nonnull arr[1];
+ arr[0] = p;
+}
+
+struct S1 {
+ int *_Nonnull mptr;
+};
+
+// CHECK-LABEL: define void @nonnull_assign3
+#line 500
+void nonnull_assign3(int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]]
+ struct S1 s;
+ s.mptr = p;
+}
+
+// CHECK-LABEL: define void @nonnull_init1
+#line 600
+void nonnull_init1(int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]]
+ int *_Nonnull local = p;
+}
+
+// CHECK-LABEL: define void @nonnull_init2
+#line 700
+void nonnull_init2(int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]]
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]]
+ int *_Nonnull arr[] = {p, p};
+}
+
+// CHECK-LABEL: define i32* @nonnull_retval2
+#line 800
+int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this.
+ int *_Nonnull arg2, //< Test this.
+ int *_Nullable arg3, //< Don't test the rest.
+ int *arg4,
+ int arg5, ...) {
+ // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize
+ // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize
+ // CHECK: [[ARG2CMP:%.*]] = icmp ne i32* %arg2, null, !nosanitize
+ // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]]
+ // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
+ // CHECK: [[NULL]]:
+ // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]]
+ return arg1;
+ // CHECK: [[NONULL]]:
+ // CHECK-NEXT: ret i32*
+}
+
+@interface A
++(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1;
+-(int *_Nonnull) objc_method: (int *_Nonnull) arg1;
+@end
+
+@implementation A
+
+// CHECK-LABEL: define internal i32* @"\01+[A objc_clsmethod:]"
++(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 {
+ // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize
+ // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
+ // CHECK: br i1 [[DO_RV_CHECK]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
+ // CHECK: [[NULL]]:
+ // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
+ return arg1;
+ // CHECK: [[NONULL]]:
+ // CHECK-NEXT: ret i32*
+}
+
+// CHECK-LABEL: define internal i32* @"\01-[A objc_method:]"
+-(int *_Nonnull) objc_method: (int *_Nonnull) arg1 {
+ // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize
+ // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]]
+ // CHECK: br i1 [[DO_RV_CHECK]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize
+ // CHECK: [[NULL]]:
+ // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_return{{.*}}
+ return arg1;
+ // CHECK: [[NONULL]]:
+ // CHECK-NEXT: ret i32*
+}
+@end
+
+// CHECK-LABEL: define void @call_A
+void call_A(A *a, int *p) {
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
+ // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P1]])
+ [a objc_method: p];
+
+ // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize
+ // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize
+ // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize
+ // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P2]])
+ [A objc_clsmethod: p];
+}
+
+void dont_crash(int *_Nonnull p, ...) {}
+
+int main() {
+ nonnull_retval1(NULL);
+ nonnull_retval2(NULL, NULL, NULL, NULL, 0, 0, 0, 0);
+ call_func_with_nonnull_arg(NULL);
+ nonnull_assign1(NULL);
+ nonnull_assign2(NULL);
+ nonnull_assign3(NULL);
+ nonnull_init1(NULL);
+ nonnull_init2(NULL);
+ call_A(NULL, NULL);
+ dont_crash(NULL, NULL);
+ return 0;
+}