Skip to content

Commit e4dfc9f

Browse files
committed
Fix the type of the capture passed to LambdaIntroducer::addCapture in
RebuildLambdaScopeInfo Previously the type of the variable was being passed, which was causing clang to crash when a non-reference variable was captured by reference or a reference variable was captured by value by a lambda and a block nested inside the lambda body was referencing the variable. Original patch by JF Bastien. rdar://problem/47550338 Differential Revision: https://reviews.llvm.org/D58164
1 parent 2ab8065 commit e4dfc9f

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13738,13 +13738,12 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
1373813738
VarDecl *VD = C.getCapturedVar();
1373913739
if (VD->isInitCapture())
1374013740
S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);
13741-
QualType CaptureType = VD->getType();
1374213741
const bool ByRef = C.getCaptureKind() == LCK_ByRef;
1374313742
LSI->addCapture(VD, /*IsBlock*/false, ByRef,
1374413743
/*RefersToEnclosingVariableOrCapture*/true, C.getLocation(),
1374513744
/*EllipsisLoc*/C.isPackExpansion()
1374613745
? C.getEllipsisLoc() : SourceLocation(),
13747-
CaptureType, /*Invalid*/false);
13746+
I->getType(), /*Invalid*/false);
1374813747

1374913748
} else if (C.capturesThis()) {
1375013749
LSI->addThisCapture(/*Nested*/ false, C.getLocation(), I->getType(),

clang/test/CodeGenObjCXX/block-nested-in-lambda.mm

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -std=c++11 -fblocks -fobjc-arc -o - %s | FileCheck %s
1+
// RUN: %clang_cc1 -triple=x86_64-apple-darwin10 -emit-llvm -std=c++14 -fblocks -fobjc-arc -o - %s | FileCheck %s
22

33
// CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 }
4+
// CHECK: %[[S:.*]] = type { i32 }
5+
// CHECK: %[[CLASS_ANON_2:.*]] = type { %[[S]]* }
6+
// CHECK: %[[CLASS_ANON_3:.*]] = type { %[[S]] }
47

58
// CHECK: %[[BLOCK_CAPTURED0:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>, <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i32*, i32* }>* %[[BLOCK:.*]], i32 0, i32 5
69
// CHECK: %[[V0:.*]] = getelementptr inbounds %[[LAMBDA_CLASS:.*]], %[[LAMBDA_CLASS]]* %[[THIS:.*]], i32 0, i32 0
@@ -33,7 +36,7 @@ void block_in_lambda(int &s1, int &s2) {
3336
// reference.
3437

3538
// CHECK-LABEL: define void @_ZN18CaptureByReference5test0Ev(
36-
// CHECK-LABEL: define internal void @"_ZZN18CaptureByReference5test0EvENK3$_1clEv"(
39+
// CHECK-LABEL: define internal void @"_ZZN18CaptureByReference5test0EvENK3$_3clEv"(
3740
// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8** }>* %{{.*}}, i32 0, i32 4
3841
// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i64 }* @"__block_descriptor_40_e5_v8\01?0ls32l8" to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
3942

@@ -46,10 +49,60 @@ void test0() {
4649
// is captured by reference.
4750

4851
// CHECK-LABEL: define void @_ZN18CaptureByReference5test1Ev(
49-
// CHECK-LABEL: define internal void @"_ZZN18CaptureByReference5test1EvENK3$_2clEv"(
52+
// CHECK-LABEL: define internal void @"_ZZN18CaptureByReference5test1EvENK3$_4clEv"(
5053
// CHECK: %[[BLOCK_DESCRIPTOR:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 4
5154
// CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i64 }* @"__block_descriptor_56_8_32s40s_e5_v8\01?0l" to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %[[BLOCK_DESCRIPTOR]], align 8
5255

56+
void test1() {
57+
id a = getObj(), b = getObj(), c = getObj();
58+
[&a, b, c]{ ^{ a = 0; use(b); use(c); }(); }();
59+
}
60+
61+
struct S {
62+
int val() const;
63+
int a;
64+
S();
65+
S(const S&);
66+
S &operator=(const S&);
67+
S(S&&);
68+
S &operator=(S&&);
69+
};
70+
71+
S getS();
72+
73+
// CHECK: define internal i32 @"_ZZN18CaptureByReference5test2EvENK3$_1clIiEEDaT_"(%[[CLASS_ANON_2]]* %{{.*}}, i32 %{{.*}})
74+
// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %{{.*}}, %[[S]]* }>, align 8
75+
// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %{{.*}}, %[[S]]* }>, <{ i8*, i32, i32, i8*, %{{.*}}, %[[S]]* }>* %[[BLOCK]], i32 0, i32 5
76+
// CHECK: %[[V0:.*]] = getelementptr inbounds %[[CLASS_ANON_2]], %[[CLASS_ANON_2]]* %{{.*}}, i32 0, i32 0
77+
// CHECK: %[[V1:.*]] = load %[[S]]*, %[[S]]** %[[V0]], align 8
78+
// CHECK: store %[[S]]* %[[V1]], %[[S]]** %[[BLOCK_CAPTURED]], align 8
79+
80+
int test2() {
81+
S s;
82+
auto fn = [&](const auto a){
83+
return ^{
84+
return s.val();
85+
}();
86+
};
87+
return fn(123);
88+
}
89+
90+
// CHECK: define internal i32 @"_ZZN18CaptureByReference5test3EvENK3$_2clIiEEDaT_"(%[[CLASS_ANON_3]]* %{{.*}}, i32 %{{.*}})
91+
// CHECK: %[[BLOCK:.*]] = alloca <{ i8*, i32, i32, i8*, %{{.*}}*, %[[S]] }>, align 8
92+
// CHECK: %[[BLOCK_CAPTURED:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %{{.*}}*, %[[S]] }>, <{ i8*, i32, i32, i8*, %{{.*}}*, %[[S]] }>* %[[BLOCK]], i32 0, i32 5
93+
// CHECK: %[[V0:.*]] = getelementptr inbounds %[[CLASS_ANON_3]], %[[CLASS_ANON_3]]* %{{.*}}, i32 0, i32 0
94+
// CHECK: call void @_ZN18CaptureByReference1SC1ERKS0_(%[[S]]* %[[BLOCK_CAPTURED]], %[[S]]* {{.*}} %[[V0]])
95+
96+
int test3() {
97+
const S &s = getS();
98+
auto fn = [=](const auto a){
99+
return ^{
100+
return s.val();
101+
}();
102+
};
103+
return fn(123);
104+
}
105+
53106
// CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32s40s(
54107
// CHECK-NOT: call void @llvm.objc.storeStrong(
55108
// CHECK: %[[V4:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>, <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]*, i8*, i8*, i8** }>* %{{.*}}, i32 0, i32 5
@@ -74,9 +127,4 @@ void test0() {
74127
// CHECK-NOT: call void @llvm.objc.storeStrong(
75128
// CHECK: ret void
76129

77-
void test1() {
78-
id a = getObj(), b = getObj(), c = getObj();
79-
[&a, b, c]{ ^{ a = 0; use(b); use(c); }(); }();
80-
}
81-
82130
}

0 commit comments

Comments
 (0)