Files
clang-p2996/clang/test/CodeGenCXX/cxx1y-init-captures.cpp
Richard Smith 75e3f695fb Switch from putting init capture VarDecls in the surrounding DeclContext to
putting them in the call operator's DeclContext. This better matches the
language wording and avoids some cases where code gets confused by them for
namespace-scope lambdas and the like.

llvm-svn: 191606
2013-09-28 04:31:26 +00:00

103 lines
3.2 KiB
C++

// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
struct S {
S();
S(S &&);
~S();
};
void f() {
(void) [s(S{})] {};
}
// CHECK-LABEL: define void @_Z1fv(
// CHECK: call void @_ZN1SC1Ev(
// CHECK: call void @"_ZZ1fvEN3$_0D1Ev"(
// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D1Ev"(
// CHECK: @"_ZZ1fvEN3$_0D2Ev"(
// D2 at end of file.
void g() {
[a(1), b(2)] { return a + b; } ();
}
// CHECK-LABEL: define void @_Z1gv(
// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0
// CHECK: store i32 1, i32*
// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1
// CHECK: store i32 2, i32*
// CHECK: call i32 @"_ZZ1gvENK3$_1clEv"(
// CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_1clEv"(
// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0
// CHECK: load i32*
// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1
// CHECK: load i32*
// CHECK: add nsw i32
int h(int a) {
// CHECK-LABEL: define i32 @_Z1hi(
// CHECK: %[[A_ADDR:.*]] = alloca i32,
// CHECK: %[[OUTER:.*]] = alloca
// CHECK: store i32 {{.*}}, i32* %[[A_ADDR]],
//
// Initialize init-capture 'b(a)' by reference.
// CHECK: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 0
// CHECK: store i32* %[[A_ADDR]], i32** {{.*}},
//
// Initialize init-capture 'c(a)' by copy.
// CHECK: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 1
// CHECK: load i32* %[[A_ADDR]],
// CHECK: store i32
//
// CHECK: call i32 @"_ZZ1hiENK3$_2clEv"({{.*}}* %[[OUTER]])
return [&b(a), c(a)] {
// CHECK-LABEL: define internal i32 @"_ZZ1hiENK3$_2clEv"(
// CHECK: %[[OUTER_ADDR:.*]] = alloca
// CHECK: %[[INNER:.*]] = alloca
// CHECK: store {{.*}}, {{.*}}** %[[OUTER_ADDR]],
//
// Capture outer 'c' by reference.
// CHECK: %[[OUTER:.*]] = load {{.*}}** %[[OUTER_ADDR]]
// CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 0
// CHECK-NEXT: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 1
// CHECK-NEXT: store i32* %
//
// Capture outer 'b' by copy.
// CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 1
// CHECK-NEXT: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 0
// CHECK-NEXT: load i32** %
// CHECK-NEXT: load i32* %
// CHECK-NEXT: store i32
//
// CHECK: call i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"({{.*}}* %[[INNER]])
return [=, &c] {
// CHECK-LABEL: define internal i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"(
// CHECK: %[[INNER_ADDR:.*]] = alloca
// CHECK: store {{.*}}, {{.*}}** %[[INNER_ADDR]],
// CHECK: %[[INNER:.*]] = load {{.*}}** %[[INNER_ADDR]]
//
// Load capture of 'b'
// CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 1
// CHECK: load i32* %
//
// Load capture of 'c'
// CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 0
// CHECK: load i32** %
// CHECK: load i32* %
//
// CHECK: add nsw i32
return b + c;
} ();
} ();
}
// Ensure we can emit code for init-captures in global lambdas too.
auto global_lambda = [a = 0] () mutable { return ++a; };
int get_incremented() { return global_lambda(); }
// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D2Ev"(
// CHECK: call void @_ZN1SD1Ev(