diff options
Diffstat (limited to 'clang/test')
-rw-r--r-- | clang/test/CodeGen/block-byref-aggr.c | 4 | ||||
-rw-r--r-- | clang/test/CodeGen/blocks-seq.c | 1 | ||||
-rw-r--r-- | clang/test/CodeGen/exceptions.c | 1 | ||||
-rw-r--r-- | clang/test/CodeGen/personality.c | 1 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/block-capture.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/blocks.cpp | 1 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/debug-info-blocks.cpp | 1 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/noescape.cpp | 31 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/arc-no-arc-exceptions.m | 1 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/arc-unoptimized-byref-var.m | 1 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/blocks-1.m | 49 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/noescape.m | 52 | ||||
-rw-r--r-- | clang/test/CodeGenObjCXX/arc-blocks.mm | 11 | ||||
-rw-r--r-- | clang/test/PCH/block-helpers.cpp | 20 | ||||
-rw-r--r-- | clang/test/SemaObjCXX/blocks.mm | 8 | ||||
-rw-r--r-- | clang/test/SemaObjCXX/noescape.mm | 25 |
16 files changed, 184 insertions, 25 deletions
diff --git a/clang/test/CodeGen/block-byref-aggr.c b/clang/test/CodeGen/block-byref-aggr.c index 962f100638f..db105768993 100644 --- a/clang/test/CodeGen/block-byref-aggr.c +++ b/clang/test/CodeGen/block-byref-aggr.c @@ -9,11 +9,13 @@ Agg makeAgg(void); // cause a block copy. rdar://9309454 void test0() { __block Agg a = {100}; + ^{ (void)a; }; a = makeAgg(); } // CHECK-LABEL: define void @test0() // CHECK: [[A:%.*]] = alloca [[BYREF:%.*]], align 8 +// CHECK-NEXT: alloca <{ i8*, i32, i32, i8*, %{{.*}}*, i8* }>, align 8 // CHECK-NEXT: [[TEMP:%.*]] = alloca [[AGG]], align 4 // CHECK: [[RESULT:%.*]] = call i32 @makeAgg() // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[TEMP]], i32 0, i32 0 @@ -35,11 +37,13 @@ void test0() { // rdar://11757470 void test1() { __block Agg a, b; + ^{ (void)a; (void)b; }; a = b = makeAgg(); } // CHECK-LABEL: define void @test1() // CHECK: [[A:%.*]] = alloca [[A_BYREF:%.*]], align 8 // CHECK-NEXT: [[B:%.*]] = alloca [[B_BYREF:%.*]], align 8 +// CHECK-NEXT: alloca <{ i8*, i32, i32, i8*, %{{.*}}*, i8*, i8* }>, align 8 // CHECK-NEXT: [[TEMP:%.*]] = alloca [[AGG]], align 4 // CHECK: [[RESULT:%.*]] = call i32 @makeAgg() // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[TEMP]], i32 0, i32 0 diff --git a/clang/test/CodeGen/blocks-seq.c b/clang/test/CodeGen/blocks-seq.c index b3e672976ca..9b47fbf783d 100644 --- a/clang/test/CodeGen/blocks-seq.c +++ b/clang/test/CodeGen/blocks-seq.c @@ -11,6 +11,7 @@ int rhs(); void foo() { __block int i; + ^{ (void)i; }; i = rhs(); i += rhs(); } diff --git a/clang/test/CodeGen/exceptions.c b/clang/test/CodeGen/exceptions.c index 039ec84d2e5..57b869196ba 100644 --- a/clang/test/CodeGen/exceptions.c +++ b/clang/test/CodeGen/exceptions.c @@ -23,6 +23,7 @@ void test1() { void test2_helper(); void test2() { __block int x = 10; + ^{ (void)x; }; test2_helper(5, 6, 7); } void test2_helper(int x, int y) { diff --git a/clang/test/CodeGen/personality.c b/clang/test/CodeGen/personality.c index 1c533ce786c..59a6a9ccd69 100644 --- a/clang/test/CodeGen/personality.c +++ b/clang/test/CodeGen/personality.c @@ -26,6 +26,7 @@ extern void i(void); void f(void) { __block int i; + ^{ (void)i; }; g(^ { }); } diff --git a/clang/test/CodeGenCXX/block-capture.cpp b/clang/test/CodeGenCXX/block-capture.cpp index 623838357a3..515d64d35da 100644 --- a/clang/test/CodeGenCXX/block-capture.cpp +++ b/clang/test/CodeGenCXX/block-capture.cpp @@ -4,10 +4,12 @@ // CHECK: [[baz:%[0-9a-z_]*]] = alloca %struct.__block_byref_baz // CHECK: [[bazref:%[0-9a-z_\.]*]] = getelementptr inbounds %struct.__block_byref_baz, %struct.__block_byref_baz* [[baz]], i32 0, i32 1 // CHECK: store %struct.__block_byref_baz* [[baz]], %struct.__block_byref_baz** [[bazref]] +// CHECK: bitcast %struct.__block_byref_baz* [[baz]] to i8* // CHECK: [[disposable:%[0-9a-z_]*]] = bitcast %struct.__block_byref_baz* [[baz]] to i8* // CHECK: call void @_Block_object_dispose(i8* [[disposable]] int main() { __block int baz = [&]() { return 0; }(); + ^{ (void)baz; }; return 0; } diff --git a/clang/test/CodeGenCXX/blocks.cpp b/clang/test/CodeGenCXX/blocks.cpp index 32b1dd82dd5..3b3363dc417 100644 --- a/clang/test/CodeGenCXX/blocks.cpp +++ b/clang/test/CodeGenCXX/blocks.cpp @@ -76,6 +76,7 @@ namespace test2 { void test() { __block A a; __block B b; + ^{ (void)a; (void)b; }; } // CHECK-LABEL: define internal void @__Block_byref_object_copy diff --git a/clang/test/CodeGenCXX/debug-info-blocks.cpp b/clang/test/CodeGenCXX/debug-info-blocks.cpp index fd2f0c99e77..f47ade7d52b 100644 --- a/clang/test/CodeGenCXX/debug-info-blocks.cpp +++ b/clang/test/CodeGenCXX/debug-info-blocks.cpp @@ -9,6 +9,7 @@ struct A { void test() { __block A a; + ^{ (void)a; }; } // CHECK: !DISubprogram(name: "__Block_byref_object_copy_", diff --git a/clang/test/CodeGenCXX/noescape.cpp b/clang/test/CodeGenCXX/noescape.cpp index 90d24de3da2..40bc839788a 100644 --- a/clang/test/CodeGenCXX/noescape.cpp +++ b/clang/test/CodeGenCXX/noescape.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -fblocks -o - %s | FileCheck %s struct S { int a[4]; @@ -65,3 +65,32 @@ typedef void (*NoEscapeFunc)(__attribute__((noescape)) int *); void test3(NoEscapeFunc f, int *p) { f(p); } + +namespace TestByref { + +struct S { + S(); + ~S(); + S(const S &); + int a; +}; + +typedef void (^BlockTy)(void); +S &getS(); +void noescapefunc(__attribute__((noescape)) BlockTy); + +// Check that __block variables with reference types are handled correctly. + +// CHECK: define void @_ZN9TestByref4testEv( +// CHECK: %[[X:.*]] = alloca %[[STRUCT_TESTBYREF:.*]]*, align 8 +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>, align 8 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>, <{ i8*, i32, i32, i8*, %{{.*}}*, %[[STRUCT_TESTBYREF]]* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK: %[[V0:.*]] = load %[[STRUCT_TESTBYREF]]*, %[[STRUCT_TESTBYREF]]** %[[X]], align 8 +// CHECK: store %[[STRUCT_TESTBYREF]]* %[[V0]], %[[STRUCT_TESTBYREF]]** %[[BLOCK_CAPTURED]], align 8 + +void test() { + __block S &x = getS(); + noescapefunc(^{ (void)x; }); +} + +} diff --git a/clang/test/CodeGenObjC/arc-no-arc-exceptions.m b/clang/test/CodeGenObjC/arc-no-arc-exceptions.m index 3338ad8477b..31d1dd53763 100644 --- a/clang/test/CodeGenObjC/arc-no-arc-exceptions.m +++ b/clang/test/CodeGenObjC/arc-no-arc-exceptions.m @@ -42,6 +42,7 @@ void NSLog(id, ...); void test2(void) { @autoreleasepool { __attribute__((__blocks__(byref))) int x; + ^{ (void)x; }; NSLog(@"Address of x outside of block: %p", &x); } } diff --git a/clang/test/CodeGenObjC/arc-unoptimized-byref-var.m b/clang/test/CodeGenObjC/arc-unoptimized-byref-var.m index 9d856d659af..ffc73a44d4e 100644 --- a/clang/test/CodeGenObjC/arc-unoptimized-byref-var.m +++ b/clang/test/CodeGenObjC/arc-unoptimized-byref-var.m @@ -3,6 +3,7 @@ void test19() { __block id x; + ^{ (void)x; }; // CHECK-UNOPT-LABEL: define internal void @__Block_byref_object_copy // CHECK-UNOPT: [[X:%.*]] = getelementptr inbounds [[BYREF_T:%.*]], [[BYREF_T:%.*]]* [[VAR:%.*]], i32 0, i32 6 // CHECK-UNOPT: [[X2:%.*]] = getelementptr inbounds [[BYREF_T:%.*]], [[BYREF_T:%.*]]* [[VAR1:%.*]], i32 0, i32 6 diff --git a/clang/test/CodeGenObjC/blocks-1.m b/clang/test/CodeGenObjC/blocks-1.m index 0d2c35096ae..cecb55d17a8 100644 --- a/clang/test/CodeGenObjC/blocks-1.m +++ b/clang/test/CodeGenObjC/blocks-1.m @@ -1,23 +1,31 @@ -// RUN: %clang_cc1 %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -// RUN: grep "_Block_object_dispose" %t | count 6 -// RUN: grep "__copy_helper_block_" %t | count 4 -// RUN: grep "__destroy_helper_block_" %t | count 4 -// RUN: grep "__Block_byref_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_object_dispose_" %t | count 2 -// RUN: not grep "i32 135)" %t -// RUN: grep "_Block_object_assign" %t | count 4 -// RUN: grep "objc_read_weak" %t | count 2 -// RUN: grep "objc_assign_weak" %t | count 3 -// RUN: %clang_cc1 -x objective-c++ %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 -// RUN: grep "_Block_object_dispose" %t | count 6 -// RUN: grep "__copy_helper_block_" %t | count 4 -// RUN: grep "__destroy_helper_block_" %t | count 4 -// RUN: grep "__Block_byref_object_copy_" %t | count 2 -// RUN: grep "__Block_byref_object_dispose_" %t | count 2 -// RUN: not grep "i32 135)" %t -// RUN: grep "_Block_object_assign" %t | count 4 -// RUN: grep "objc_read_weak" %t | count 2 -// RUN: grep "objc_assign_weak" %t | count 3 +// RUN: %clang_cc1 %s -emit-llvm -o - -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 | FileCheck %s --check-prefix=CHECK --check-prefix=OBJC +// RUN: %clang_cc1 -x objective-c++ %s -emit-llvm -o - -fobjc-gc -fblocks -triple i386-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 | FileCheck %s --check-prefix=CHECK --check-prefix=OBJCXX + +// OBJC-LABEL: define void @test1( +// OBJCXX-LABEL: define void @_Z5test1P12NSDictionary( + +// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ +// CHECK: call void @_Block_object_assign( + +// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ +// CHECK: call void @_Block_object_dispose( + +// OBJC-LABEL: define void @foo( +// OBJCXX-LABEL: define void @_Z3foov( +// CHECK: call i8* @objc_read_weak( +// CHECK: call i8* @objc_assign_weak( +// CHECK: call void @_Block_object_dispose( + +// OBJC-LABEL: define void @test2( +// OBJCXX-LABEL: define void @_Z5test2v( +// CHECK: call i8* @objc_assign_weak( +// CHECK: call void @_Block_object_dispose( + +// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ +// CHECK: call void @_Block_object_assign( + +// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ +// CHECK: call void @_Block_object_dispose( @interface NSDictionary @end @@ -30,6 +38,7 @@ void test1(NSDictionary * dict) { void foo() { __block __weak D *weakSelf; + ^{ (void)weakSelf; }; D *l; l = weakSelf; weakSelf = l; diff --git a/clang/test/CodeGenObjC/noescape.m b/clang/test/CodeGenObjC/noescape.m index b4c8bf7eaf2..c7624f24fb6 100644 --- a/clang/test/CodeGenObjC/noescape.m +++ b/clang/test/CodeGenObjC/noescape.m @@ -8,6 +8,7 @@ union U { long long *ll; } __attribute__((transparent_union)); +void escapingFunc0(BlockTy); void noescapeFunc0(id, __attribute__((noescape)) BlockTy); void noescapeFunc1(__attribute__((noescape)) int *); void noescapeFunc2(__attribute__((noescape)) id); @@ -21,6 +22,9 @@ void noescapeFunc3(__attribute__((noescape)) union U); // When the block is non-escaping, copy/dispose helpers aren't generated, so the // block layout string must include information about __strong captures. +// CHECK-NOARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_B0]]*, i32, i32, i8*, %[[STRUCT_S0:.*]] } +// CHECK-ARC: %[[STRUCT_BLOCK_BYREF_B0:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_B0]]*, i32, i32, i8*, i8*, i8*, %[[STRUCT_S0:.*]] } +// CHECK: %[[STRUCT_S0]] = type { i8*, i8* } // CHECK: @[[BLOCK_DESCIPTOR_TMP_2:.*ls32l8"]] = linkonce_odr hidden unnamed_addr constant { i64, i64, i8*, i64 } { i64 0, i64 40, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i64 256 }, align 8 // CHECK-LABEL: define void @test0( @@ -102,7 +106,7 @@ void test5(BlockTy2 b, int *p) { // CHECK-NOARC: %[[V1:.*]] = load i8*, i8** %[[B_ADDR]], align 8 // CHECK-NOARC: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED]], align 8 // CHECK-ARC: %[[V2:.*]] = load i8*, i8** %[[B_ADDR]], align 8 -// CHECK-ARC: %[[V3:.*]] = call i8* @objc_retain(i8* %[[V2]]) #3 +// CHECK-ARC: %[[V3:.*]] = call i8* @objc_retain(i8* %[[V2]]) // CHECK-ARC: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED]], align 8 // CHECK: call void @noescapeFunc0( // CHECK-ARC: call void @objc_storeStrong(i8** %[[V0]], i8* null) @@ -118,3 +122,49 @@ void func(id); void test6(id a, id b) { noescapeFunc0(a, ^{ func(b); }); } + +// We don't need either the byref helper functions or the byref structs for +// __block variables that are not captured by escaping blocks. + +// CHECK: define void @test7( +// CHECK: alloca i8*, align 8 +// CHECK: %[[B0:.*]] = alloca i8*, align 8 +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, align 8 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>* %[[BLOCK]], i32 0, i32 5 +// CHECK: store i8** %[[B0]], i8*** %[[BLOCK_CAPTURED]], align 8 + +// CHECK-ARC-NOT: define internal void @__Block_byref_object_copy_ +// CHECK-ARC-NOT: define internal void @__Block_byref_object_dispose_ + +void test7() { + id a; + __block id b0; + noescapeFunc0(a, ^{ (void)b0; }); +} + +// __block variables captured by escaping blocks need byref helper functions. + +// CHECK: define void @test8( +// CHECK: %[[A:.*]] = alloca i8*, align 8 +// CHECK: %[[B0:.*]] = alloca %[[STRUCT_BLOCK_BYREF_B0]], align 8 +// CHECK: alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 +// CHECK: %[[BLOCK1:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, align 8 +// CHECK: %[[BLOCK_CAPTURED7:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8* }>* %[[BLOCK1]], i32 0, i32 5 +// CHECK: %[[V3:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_B0]]* %[[B0]] to i8* +// CHECK: store i8* %[[V3]], i8** %[[BLOCK_CAPTURED7]], align 8 + +// CHECK-ARC: define internal void @__Block_byref_object_copy_ +// CHECK-ARC: define internal void @__Block_byref_object_dispose_ +// CHECK: define linkonce_odr hidden void @__copy_helper_block_ +// CHECK: define linkonce_odr hidden void @__destroy_helper_block_ + +struct S0 { + id a, b; +}; + +void test8() { + id a; + __block struct S0 b0; + noescapeFunc0(a, ^{ (void)b0; }); + escapingFunc0(^{ (void)b0; }); +} diff --git a/clang/test/CodeGenObjCXX/arc-blocks.mm b/clang/test/CodeGenObjCXX/arc-blocks.mm index ef0561bad53..4791aff0b3b 100644 --- a/clang/test/CodeGenObjCXX/arc-blocks.mm +++ b/clang/test/CodeGenObjCXX/arc-blocks.mm @@ -3,9 +3,9 @@ // RUN: %clang_cc1 -std=gnu++98 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -o - %s | FileCheck -check-prefix CHECK-NOEXCP %s // CHECK: [[A:.*]] = type { i64, [10 x i8*] } +// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } // CHECK: %[[STRUCT_TEST1_S0:.*]] = type { i32 } // CHECK: %[[STRUCT_TRIVIAL_INTERNAL:.*]] = type { i32 } -// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } // CHECK: [[LAYOUT0:@.*]] = private unnamed_addr constant [3 x i8] c" 9\00" @@ -20,6 +20,7 @@ namespace test0 { void foo() { __block A v; + ^{ (void)v; }; } // CHECK-LABEL: define void @_ZN5test03fooEv() // CHECK: [[V:%.*]] = alloca [[BYREF_A:%.*]], align 8 @@ -32,7 +33,8 @@ namespace test0 { // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7 // CHECK-NEXT: call void @_ZN5test01AC1Ev([[A]]* [[T0]]) // CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds [[BYREF_A]], [[BYREF_A]]* [[V]], i32 0, i32 7 - // CHECK-NEXT: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8* + // CHECK: bitcast [[BYREF_A]]* [[V]] to i8* + // CHECK: [[T1:%.*]] = bitcast [[BYREF_A]]* [[V]] to i8* // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T1]], i32 8) // CHECK-NEXT: call void @_ZN5test01AD1Ev([[A]]* [[T0]]) // CHECK-NEXT: ret void @@ -53,6 +55,11 @@ namespace test0 { // CHECK-NEXT: ret void } +// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_ +// CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_ +// CHECK-LABEL-O1: define linkonce_odr hidden void @__copy_helper_block_ +// CHECK-LABEL-O1: define linkonce_odr hidden void @__destroy_helper_block_ + namespace test1 { // Check that copy/dispose helper functions are exception safe. diff --git a/clang/test/PCH/block-helpers.cpp b/clang/test/PCH/block-helpers.cpp index 046bbb428cd..02d4ceecf35 100644 --- a/clang/test/PCH/block-helpers.cpp +++ b/clang/test/PCH/block-helpers.cpp @@ -1,6 +1,26 @@ // RUN: %clang_cc1 -x c++-header -triple x86_64-apple-darwin11 -emit-pch -fblocks -fexceptions -o %t %S/block-helpers.h // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -include-pch %t -emit-llvm -fblocks -fexceptions -o - %s | FileCheck %s +// CHECK: %[[STRUCT_BLOCK_BYREF_X:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_X]]*, i32, i32, i8*, i8*, %[[STRUCT_S0:.*]] } +// CHECK: %[[STRUCT_S0]] = type { i32 } +// CHECK: %[[STRUCT_BLOCK_BYREF_Y:.*]] = type { i8*, %[[STRUCT_BLOCK_BYREF_Y]]*, i32, i32, i8*, i8*, %[[STRUCT_S0]] } +// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } + +// Check that byref structs are allocated for x and y. + +// CHECK-LABEL: define linkonce_odr void @_ZN1S1mEv( +// CHECK: %[[X:.*]] = alloca %[[STRUCT_BLOCK_BYREF_X]], align 8 +// CHECK: %[[Y:.*]] = alloca %[[STRUCT_BLOCK_BYREF_Y]], align 8 +// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, align 8 +// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>* %[[BLOCK]], i32 0, i32 5 +// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_X]]* %[[X]] to i8* +// CHECK: store i8* %[[V0]], i8** %[[BLOCK_CAPTURED]], align 8 +// CHECK: %[[BLOCK_CAPTURED10:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8* }>* %[[BLOCK]], i32 0, i32 6 +// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_BLOCK_BYREF_Y]]* %[[Y]] to i8* +// CHECK: store i8* %[[V1]], i8** %[[BLOCK_CAPTURED10]], align 8 + +// CHECK-LABEL: define internal void @___ZN1S1mEv_block_invoke( + // The second call to block_object_assign should be an invoke. // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_e8_32rc40rc( diff --git a/clang/test/SemaObjCXX/blocks.mm b/clang/test/SemaObjCXX/blocks.mm index bdd5538e92b..5f735241720 100644 --- a/clang/test/SemaObjCXX/blocks.mm +++ b/clang/test/SemaObjCXX/blocks.mm @@ -76,21 +76,27 @@ namespace N1 { } // Make sure we successfully instantiate the copy constructor of a -// __block variable's type. +// __block variable's type when the variable is captured by an escaping block. namespace N2 { template <int n> struct A { A() {} A(const A &other) { int invalid[-n]; // expected-error 2 {{array with a negative size}} } + void m() {} }; + typedef void (^BlockFnTy)(); + void func(BlockFnTy); + void test1() { __block A<1> x; // expected-note {{requested here}} + func(^{ x.m(); }); } template <int n> void test2() { __block A<n> x; // expected-note {{requested here}} + func(^{ x.m(); }); } template void test2<2>(); } diff --git a/clang/test/SemaObjCXX/noescape.mm b/clang/test/SemaObjCXX/noescape.mm index 9432a3a48a0..efa2a76d668 100644 --- a/clang/test/SemaObjCXX/noescape.mm +++ b/clang/test/SemaObjCXX/noescape.mm @@ -8,6 +8,7 @@ struct S { void m(); }; +void escapingFunc0(BlockTy); void noescapeFunc0(id, __attribute__((noescape)) BlockTy); void noescapeFunc1(id, [[clang::noescape]] BlockTy); void noescapeFunc2(__attribute__((noescape)) int *); // expected-note {{previous declaration is here}} @@ -127,3 +128,27 @@ __attribute__((objc_root_class)) -(void) m1:(int*) p { } @end + +struct S6 { + S6(); + S6(const S6 &) = delete; // expected-note 3 {{'S6' has been explicitly marked deleted here}} + int f; +}; + +void test1() { + id a; + // __block variables that are not captured by escaping blocks don't + // necessitate having accessible copy constructors. + __block S6 b0; + __block S6 b1; // expected-error {{call to deleted constructor of 'S6'}} + __block S6 b2; // expected-error {{call to deleted constructor of 'S6'}} + __block S6 b3; // expected-error {{call to deleted constructor of 'S6'}} + + noescapeFunc0(a, ^{ (void)b0; }); + escapingFunc0(^{ (void)b1; }); + { + noescapeFunc0(a, ^{ (void)b0; (void)b1; }); + } + noescapeFunc0(a, ^{ escapingFunc0(^{ (void)b2; }); }); + escapingFunc0(^{ noescapeFunc0(a, ^{ (void)b3; }); }); +} |