summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-09-28 04:02:39 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-09-28 04:02:39 +0000
commitbb13c9a49d08b56b9a8f04bd76ad3a7972bcc478 (patch)
tree65d9331fbe86ec254e57c2043d96dde642427196 /clang/test
parent45015d9796c116c97510919179efdef9f18a99db (diff)
downloadbcm5719-llvm-bb13c9a49d08b56b9a8f04bd76ad3a7972bcc478.tar.gz
bcm5719-llvm-bb13c9a49d08b56b9a8f04bd76ad3a7972bcc478.zip
Per latest drafting, switch to implementing init-captures as if by declaring
and capturing a variable declaration, and complete the implementation of them. llvm-svn: 191605
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Analysis/lambdas.cpp2
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp57
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp2
-rw-r--r--clang/test/CodeGenCXX/cxx1y-init-captures.cpp98
-rw-r--r--clang/test/PCH/cxx1y-init-captures.cpp28
-rw-r--r--clang/test/Parser/cxx0x-lambda-expressions.cpp10
6 files changed, 157 insertions, 40 deletions
diff --git a/clang/test/Analysis/lambdas.cpp b/clang/test/Analysis/lambdas.cpp
index 77b36c42cfa..33e216b57ec 100644
--- a/clang/test/Analysis/lambdas.cpp
+++ b/clang/test/Analysis/lambdas.cpp
@@ -10,7 +10,7 @@ void f(X x) { (void) [x]{}; }
// CHECK: 1: x
// CHECK: 2: [B1.1] (ImplicitCastExpr, NoOp, const struct X)
// CHECK: 3: [B1.2] (CXXConstructExpr, struct X)
-// CHECK: 4: [=x] {
+// CHECK: 4: [x] {
// CHECK: }
// CHECK: 5: (void)[B1.4] (CStyleCastExpr, ToVoid, void)
// CHECK: Preds (1): B2
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
index be39ded6ff3..6be200dd54e 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
@@ -1,34 +1,26 @@
// RUN: %clang_cc1 -std=c++1y %s -verify
-// For every init-capture a non-static data member named by the identifier of
-// the init-capture is declared in the closure type.
-const char *has_member_x = [x("hello")] {}.x;
-// This member is not a bit-field...
-auto capturing_lambda = [n(0)] {};
-int decltype(capturing_lambda)::*mem_ptr = &decltype(capturing_lambda)::n;
-// ... and not mutable.
-const auto capturing_lambda_copy = capturing_lambda;
-int &n = capturing_lambda_copy.n; // expected-error {{drops qualifiers}}
+const char *has_no_member = [x("hello")] {}.x; // expected-error {{no member named 'x'}}
-// The type of that member [...is that of a...] variable declaration of the form
-// "auto init-capture ;"...
-auto with_float = [f(1.0f)] {};
-float &f = with_float.f;
-// ... except that the variable name is replaced by a unique identifier.
-auto with_float_2 = [&f(f)] {}; // ok, refers to outer f
-float &f2 = with_float_2.f;
+double f;
+auto with_float = [f(1.0f)] {
+ using T = decltype(f);
+ using T = float;
+};
+auto with_float_2 = [&f(f)] { // ok, refers to outer f
+ using T = decltype(f);
+ using T = double&;
+};
-// Within the lambda-expression's lambda-declarator (FIXME) and
-// compound-statement, the identifier in the init-capture hides any declaration
+// Within the lambda-expression's compound-statement,
+// the identifier in the init-capture hides any declaration
// of the same name in scopes enclosing the lambda-expression.
void hiding() {
char c;
(void) [c("foo")] {
static_assert(sizeof(c) == sizeof(const char*), "");
};
- (void) [c("bar")] () -> decltype(c) {
- // FIXME: the 'c' in the return type should be the init-capture, not the
- // outer c.
+ (void) [c("bar")] () -> decltype(c) { // outer c, not init-capture
return "baz"; // expected-error {{cannot initialize}}
};
}
@@ -54,22 +46,16 @@ int overload_fn(int);
auto bad_init_1 = [a()] {}; // expected-error {{expected expression}}
auto bad_init_2 = [a(1, 2)] {}; // expected-error {{initializer for lambda capture 'a' contains multiple expressions}}
auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}}
-auto bad_init_4 = [a(void_fn())] {}; // expected-error {{field has incomplete type 'void'}}
+auto bad_init_4 = [a(void_fn())] {}; // expected-error {{has incomplete type 'void'}}
auto bad_init_5 = [a(overload_fn)] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer of type '<overloaded function}}
auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer list}}
-template<typename...T> void pack_1(T...t) { [a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
+template<typename...T> void pack_1(T...t) { (void)[a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
template void pack_1<>(); // expected-note {{instantiation of}}
-auto multi_return(int a, int b) {
- return [n(a + 2*b), m(a - 2*b)] {};
-}
-auto use_multi_return() {
- auto nm = multi_return(5, 9);
- return nm.n + nm.m;
-}
-
-auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] { // expected-warning {{binding reference member 'c' to a temporary value}} expected-note {{here}}
+// FIXME: Might need lifetime extension for the temporary here.
+// See DR1695.
+auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] {
static_assert(sizeof(a) == sizeof(int), "");
static_assert(sizeof(b) == sizeof(int), "");
using T = decltype(c);
@@ -82,3 +68,10 @@ template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };
template<typename T> decltype(auto) move(T &&t) { return static_cast<typename remove_reference<T>::type&&>(t); }
auto s = [s(move(S()))] {};
+
+template<typename T> T instantiate_test(T t) {
+ [x(&t)]() { *x = 1; } (); // expected-error {{assigning to 'const char *'}}
+ return t;
+}
+int instantiate_test_1 = instantiate_test(0);
+const char *instantiate_test_2 = instantiate_test("foo"); // expected-note {{here}}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
index 174ae6d5b09..083ca1bdd37 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
@@ -66,7 +66,7 @@ void init_capture_pack_err(Args ...args) {
template<typename ...Args>
void init_capture_pack_multi(Args ...args) {
- [as(args...)] {} (); // expected-error {{initializer missing}} expected-error {{multiple}}
+ [as(args...)] {} (); // expected-error {{initializer missing for lambda capture 'as'}} expected-error {{multiple}}
}
template void init_capture_pack_multi(); // expected-note {{instantiation}}
template void init_capture_pack_multi(int);
diff --git a/clang/test/CodeGenCXX/cxx1y-init-captures.cpp b/clang/test/CodeGenCXX/cxx1y-init-captures.cpp
new file mode 100644
index 00000000000..6258cda3b0e
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx1y-init-captures.cpp
@@ -0,0 +1,98 @@
+// 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;
+ } ();
+ } ();
+}
+
+// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D2Ev"(
+// CHECK: call void @_ZN1SD1Ev(
diff --git a/clang/test/PCH/cxx1y-init-captures.cpp b/clang/test/PCH/cxx1y-init-captures.cpp
new file mode 100644
index 00000000000..3c8fc149d84
--- /dev/null
+++ b/clang/test/PCH/cxx1y-init-captures.cpp
@@ -0,0 +1,28 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -verify %s
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s
+
+#ifndef HEADER
+#define HEADER
+
+auto counter = [a(0)] () mutable { return a++; };
+int x = counter();
+
+template<typename T> void f(T t) {
+ [t(t)] { int n = t; } ();
+}
+
+#else
+
+int y = counter();
+
+void g() {
+ f(0); // ok
+ // expected-error@15 {{lvalue of type 'const char *const'}}
+ f("foo"); // expected-note {{here}}
+}
+
+#endif
diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp
index 76c1e0e7cec..426e530251f 100644
--- a/clang/test/Parser/cxx0x-lambda-expressions.cpp
+++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp
@@ -52,18 +52,16 @@ class C {
// We support init-captures in C++11 as an extension.
int z;
void init_capture() {
- // FIXME: These diagnostics should all disappear once semantic analysis
- // for init-captures is complete.
- [n(0)] () -> int { return ++n; }; // expected-error {{non-static data member}}
+ [n(0)] () mutable -> int { return ++n; };
[n{0}] { return; }; // expected-error {{<initializer_list>}}
- [n = 0] { return ++n; }; // expected-error {{non-static data member}}
+ [n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}}
[n = {0}] { return; }; // expected-error {{<initializer_list>}}
[a([&b = z]{})](){};
int x = 4;
auto y = [&r = x, x = x + 1]() -> int {
- r += 2; // expected-error {{non-static data member}}
- return x + 2; // expected-error {{non-static data member}}
+ r += 2;
+ return x + 2;
} ();
}
};
OpenPOWER on IntegriCloud