diff options
author | Akira Hatanaka <ahatanaka@apple.com> | 2018-04-27 04:21:51 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-04-27 04:21:51 +0000 |
commit | 71c661e65b58405384a68b92ad3eee1c4e7baaf3 (patch) | |
tree | 0d8d9c83f3891f8afb86d07fc7bd3e3d6c319566 /test/CodeGenObjCXX | |
parent | 1433b05edb4591d8330c4534d8745058cd6d831a (diff) |
[CodeGen] Avoid destructing a callee-destructued struct type in a
function if a function delegates to another function.
Fix a bug introduced in r328731, which caused a struct with ObjC __weak
fields that was passed to a function to be destructed twice, once in the
callee function and once in another function the callee function
delegates to. To prevent this, keep track of the callee-destructed
structs passed to a function and disable their cleanups at the point of
the call to the delegated function.
rdar://problem/39194693
Differential Revision: https://reviews.llvm.org/D45382
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@331016 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenObjCXX')
-rw-r--r-- | test/CodeGenObjCXX/arc-forwarded-lambda-call.mm | 20 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-special-member-functions.mm | 62 | ||||
-rw-r--r-- | test/CodeGenObjCXX/lambda-expressions.mm | 28 |
3 files changed, 108 insertions, 2 deletions
diff --git a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm index 35abe19183..0a575c7697 100644 --- a/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm +++ b/test/CodeGenObjCXX/arc-forwarded-lambda-call.mm @@ -10,6 +10,17 @@ void test0(id x) { // CHECK-NEXT: ret i8* [[T2]] } +// Check that the delegating block invoke function doesn't destruct the Weak +// object that is passed. + +// CHECK-LABEL: define internal void @___Z8testWeakv_block_invoke( +// CHECK: call void @"_ZZ8testWeakvENK3$_2clE4Weak"( +// CHECK-NEXT: ret void + +// CHECK-LABEL: define internal void @"_ZZ8testWeakvENK3$_2clE4Weak"( +// CHECK: call void @_ZN4WeakD1Ev( +// CHECK-NEXT: ret void + id test1_rv; void test1() { @@ -21,3 +32,12 @@ void test1() { // CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]]) // CHECK-NEXT: ret i8* [[T2]] } + +struct Weak { + __weak id x; +}; + +void testWeak() { + extern void testWeak_helper(void (^)(Weak)); + testWeak_helper([](Weak){}); +} diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm index 278c779481..d620187d70 100644 --- a/test/CodeGenObjCXX/arc-special-member-functions.mm +++ b/test/CodeGenObjCXX/arc-special-member-functions.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fobjc-arc -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -fobjc-arc -fblocks -triple x86_64-apple-darwin10.0.0 -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s struct ObjCMember { id member; @@ -12,6 +12,59 @@ struct ObjCBlockMember { int (^bp)(int); }; +// CHECK: %[[STRUCT_CONTAINSWEAK:.*]] = type { %[[STRUCT_WEAK:.*]] } +// CHECK: %[[STRUCT_WEAK]] = type { i8* } + +// The Weak object that is passed is destructed in this constructor. + +// CHECK: define void @_ZN12ContainsWeakC2E4Weak( +// CHECK: call void @_ZN4WeakC1ERKS_( +// CHECK: call void @_ZN4WeakD1Ev( + +// Check that the Weak object passed to this constructor is not destructed after +// the delegate constructor is called. + +// CHECK: define void @_ZN12ContainsWeakC1E4Weak( +// CHECK: call void @_ZN12ContainsWeakC2E4Weak( +// CHECK-NEXT: ret void + +struct Weak { + Weak(id); + __weak id x; +}; + +struct ContainsWeak { + ContainsWeak(Weak); + Weak w; +}; + +ContainsWeak::ContainsWeak(Weak a) : w(a) {} + +// The Weak object that is passed is destructed in this constructor. + +// CHECK: define void @_ZN4BaseC2E4Weak( +// CHECK: call void @_ZN4WeakD1Ev( +// CHECK: ret void + +// Check that the Weak object passed to this constructor is not destructed after +// the delegate constructor is called. + +// CHECK: define linkonce_odr void @_ZN7DerivedCI14BaseE4Weak( +// CHECK: call void @_ZN7DerivedCI24BaseE4Weak( +// CHECK-NEXT: ret void + +struct Base { + Base(Weak); +}; + +Base::Base(Weak a) {} + +struct Derived : Base { + using Base::Base; +}; + +Derived d(Weak(0)); + // CHECK-LABEL: define void @_Z42test_ObjCMember_default_construct_destructv( void test_ObjCMember_default_construct_destruct() { // CHECK: call void @_ZN10ObjCMemberC1Ev @@ -111,6 +164,13 @@ void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) { // CHECK-NEXT: call void @objc_release(i8* [[T7]]) // CHECK-NEXT: ret +// Check that the Weak object passed to this constructor is not destructed after +// the delegate constructor is called. + +// CHECK: define linkonce_odr void @_ZN7DerivedCI24BaseE4Weak( +// CHECK: call void @_ZN4BaseC2E4Weak( +// CHECK-NEXT: ret void + // Implicitly-generated default constructor for ObjCMember // CHECK-LABEL: define linkonce_odr void @_ZN10ObjCMemberC2Ev // CHECK-NOT: objc_release diff --git a/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm index c8247e2e0a..f60655c61b 100644 --- a/test/CodeGenObjCXX/lambda-expressions.mm +++ b/test/CodeGenObjCXX/lambda-expressions.mm @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks -fobjc-arc | FileCheck -check-prefix=ARC %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks -fobjc-arc -fobjc-runtime-has-weak -DWEAK_SUPPORTED | FileCheck -check-prefix=ARC %s // RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks | FileCheck -check-prefix=MRC %s typedef int (^fp)(); @@ -138,5 +138,31 @@ namespace BlockInLambda { } @end +// Check that the delegating invoke function doesn't destruct the Weak object +// that is passed. + +// ARC-LABEL: define internal void @"_ZZN14LambdaDelegate4testEvEN3$_58__invokeENS_4WeakE"( +// ARC: call void @"_ZZN14LambdaDelegate4testEvENK3$_5clENS_4WeakE"( +// ARC-NEXT: ret void + +// ARC-LABEL: define internal void @"_ZZN14LambdaDelegate4testEvENK3$_5clENS_4WeakE"( +// ARC: call void @_ZN14LambdaDelegate4WeakD1Ev( + +#ifdef WEAK_SUPPORTED + +namespace LambdaDelegate { + +struct Weak { + __weak id x; +}; + +void test() { + void (*p)(Weak) = [](Weak a) { }; +} + +}; + +#endif + // ARC: attributes [[NUW]] = { noinline nounwind{{.*}} } // MRC: attributes [[NUW]] = { noinline nounwind{{.*}} } |