mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 03:06:06 +00:00

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. This reapplies r331016, which was reverted in r331019 because it caused an assertion to fail in EmitDelegateCallArg on a windows bot. I made changes to EmitDelegateCallArg so that it doesn't try to deactivate cleanups for structs that have trivial destructors (cleanups for those structs are never pushed to the cleanup stack in EmitParmDecl). rdar://problem/39194693 Differential Revision: https://reviews.llvm.org/D45382 llvm-svn: 331020
44 lines
1.5 KiB
Plaintext
44 lines
1.5 KiB
Plaintext
// RUN: %clang_cc1 -triple x86_64-apple-macosx10.12.0 -emit-llvm -disable-llvm-passes -O3 -fblocks -fobjc-arc -fobjc-runtime-has-weak -std=c++11 -o - %s | FileCheck %s
|
|
|
|
void test0(id x) {
|
|
extern void test0_helper(id (^)(void));
|
|
test0_helper([=]() { return x; });
|
|
// CHECK-LABEL: define internal i8* @___Z5test0P11objc_object_block_invoke
|
|
// CHECK: [[T0:%.*]] = call i8* @"_ZZ5test0P11objc_objectENK3$_0clEv"
|
|
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
|
|
// CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
|
|
// 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() {
|
|
extern void test1_helper(id (*)(void));
|
|
test1_helper([](){ return test1_rv; });
|
|
// CHECK-LABEL: define internal i8* @"_ZZ5test1vEN3$_18__invokeEv"
|
|
// CHECK: [[T0:%.*]] = call i8* @"_ZZ5test1vENK3$_1clEv"
|
|
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
|
|
// 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){});
|
|
}
|