summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-05-16 06:20:58 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-05-16 06:20:58 +0000
commitba71c085234044f8291b82749552a79d01f99631 (patch)
treead88c0f301afad274d85c38231e034b26b8bd300 /clang/test
parentad9971d793e26c6d2ea28353f5b4dc6a2ee19833 (diff)
downloadbcm5719-llvm-ba71c085234044f8291b82749552a79d01f99631.tar.gz
bcm5719-llvm-ba71c085234044f8291b82749552a79d01f99631.zip
First pass of semantic analysis for init-captures: check the initializer, build
a FieldDecl from it, and propagate both into the closure type and the LambdaExpr. You can't do much useful with them yet -- you can't use them within the body of the lambda, because we don't have a representation for "the this of the lambda, not the this of the enclosing context". We also don't have support or a representation for a nested capture of an init-capture yet, which was intended to work despite not being allowed by the current standard wording. llvm-svn: 181985
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp84
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp23
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp3
-rw-r--r--clang/test/PCH/cxx11-lambdas.mm9
-rw-r--r--clang/test/Parser/cxx0x-lambda-expressions.cpp18
-rw-r--r--clang/test/Parser/objcxx0x-lambda-expressions.mm8
6 files changed, 132 insertions, 13 deletions
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
new file mode 100644
index 00000000000..0eec331b28c
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
@@ -0,0 +1,84 @@
+// 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}}
+
+// 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;
+
+// Within the lambda-expression's lambda-declarator (FIXME) and
+// 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.
+ return "baz"; // expected-error {{cannot initialize}}
+ };
+}
+
+struct ExplicitCopy {
+ ExplicitCopy(); // expected-note 2{{not viable}}
+ explicit ExplicitCopy(const ExplicitCopy&);
+};
+auto init_kind_1 = [ec(ExplicitCopy())] {};
+auto init_kind_2 = [ec = ExplicitCopy()] {}; // expected-error {{no matching constructor}}
+
+template<typename T> void init_kind_template() {
+ auto init_kind_1 = [ec(T())] {};
+ auto init_kind_2 = [ec = T()] {}; // expected-error {{no matching constructor}}
+}
+template void init_kind_template<int>();
+template void init_kind_template<ExplicitCopy>(); // expected-note {{instantiation of}}
+
+void void_fn();
+int overload_fn();
+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_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 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)] {
+ static_assert(sizeof(a) == sizeof(int), "");
+ static_assert(sizeof(b) == sizeof(int), "");
+ using T = decltype(c);
+ using T = const int &;
+};
+auto b = [a{0}] {}; // expected-error {{include <initializer_list>}}
+
+struct S { S(); S(S&&); };
+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()))] {};
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 82fc04a48fb..174ae6d5b09 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
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify
void print();
@@ -56,3 +57,25 @@ void variadic_lambda(Args... args) {
}
template void variadic_lambda(int*, float*, double*);
+
+template<typename ...Args>
+void init_capture_pack_err(Args ...args) {
+ [as(args)...] {} (); // expected-error {{expected ','}}
+ [as...(args)]{} (); // expected-error {{expected ','}}
+}
+
+template<typename ...Args>
+void init_capture_pack_multi(Args ...args) {
+ [as(args...)] {} (); // expected-error {{initializer missing}} expected-error {{multiple}}
+}
+template void init_capture_pack_multi(); // expected-note {{instantiation}}
+template void init_capture_pack_multi(int);
+template void init_capture_pack_multi(int, int); // expected-note {{instantiation}}
+
+template<typename ...Args>
+void init_capture_pack_outer(Args ...args) {
+ print([as(args)] { return sizeof(as); } () ...);
+}
+template void init_capture_pack_outer();
+template void init_capture_pack_outer(int);
+template void init_capture_pack_outer(int, int);
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
index d1384f19dd1..408fb75f809 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p8.cpp
@@ -26,4 +26,7 @@ void S2::f(int i) {
(void)[=, this]{ }; // expected-error{{'this' cannot be explicitly captured}}
(void)[=]{ this->g(i); };
(void)[i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
+ (void)[i(0), i(1)]{ }; // expected-error{{'i' can appear only once in a capture list}}
+ (void)[i, i(1)]{ }; // expected-error{{'i' can appear only once in a capture list}}
+ (void)[i(0), i]{ }; // expected-error{{'i' can appear only once in a capture list}}
}
diff --git a/clang/test/PCH/cxx11-lambdas.mm b/clang/test/PCH/cxx11-lambdas.mm
index c00ec638075..807bf230679 100644
--- a/clang/test/PCH/cxx11-lambdas.mm
+++ b/clang/test/PCH/cxx11-lambdas.mm
@@ -33,6 +33,11 @@ inline int to_block_pointer(int n) {
return block(17);
}
+template<typename T>
+int init_capture(T t) {
+ return [&, x(t)] { return sizeof(x); };
+}
+
#else
// CHECK-PRINT: T add_slowly
@@ -45,4 +50,8 @@ int add(int x, int y) {
// CHECK-PRINT: inline int add_int_slowly_twice
// CHECK-PRINT: lambda = [&] (int z)
+
+// CHECK-PRINT: init_capture
+// CHECK-PRINT: [&, x( t )]
+
#endif
diff --git a/clang/test/Parser/cxx0x-lambda-expressions.cpp b/clang/test/Parser/cxx0x-lambda-expressions.cpp
index d7dc7d3a473..76c1e0e7cec 100644
--- a/clang/test/Parser/cxx0x-lambda-expressions.cpp
+++ b/clang/test/Parser/cxx0x-lambda-expressions.cpp
@@ -54,16 +54,16 @@ class C {
void init_capture() {
// FIXME: These diagnostics should all disappear once semantic analysis
// for init-captures is complete.
- [n(0)] () -> int { return ++n; }; // expected-error {{not supported}} expected-error {{undeclared}}
- [n{0}] { return; }; // expected-error {{not supported}}
- [n = 0] { return ++n; }; // expected-error {{not supported}} expected-error {{undeclared}}
- [n = {0}] { return; }; // expected-error {{not supported}}
- [a([&b = z]{})](){}; // expected-error 2{{not supported}}
+ [n(0)] () -> int { return ++n; }; // expected-error {{non-static data member}}
+ [n{0}] { return; }; // expected-error {{<initializer_list>}}
+ [n = 0] { return ++n; }; // expected-error {{non-static data member}}
+ [n = {0}] { return; }; // expected-error {{<initializer_list>}}
+ [a([&b = z]{})](){};
- int x = 4; // expected-note {{here}}
- auto y = [&r = x, x = x + 1]() -> int { // expected-error 2{{not supported}} expected-note {{here}}
- r += 2; // expected-error {{undeclared}}
- return x + 2; // expected-error {{implicitly captured}}
+ 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}}
} ();
}
};
diff --git a/clang/test/Parser/objcxx0x-lambda-expressions.mm b/clang/test/Parser/objcxx0x-lambda-expressions.mm
index 94e47ccd3e0..b2a75f2edbb 100644
--- a/clang/test/Parser/objcxx0x-lambda-expressions.mm
+++ b/clang/test/Parser/objcxx0x-lambda-expressions.mm
@@ -18,10 +18,10 @@ class C {
[=,&foo] () {};
[this] () {};
- [foo(bar)] () {}; // expected-error {{not supported}}
- [foo = bar] () {}; // expected-error {{not supported}}
- [foo{bar}] () {}; // expected-error {{not supported}}
- [foo = {bar}] () {}; // expected-error {{not supported}}
+ [foo(bar)] () {};
+ [foo = bar] () {};
+ [foo{bar}] () {}; // expected-error {{<initializer_list>}}
+ [foo = {bar}] () {}; // expected-error {{<initializer_list>}}
[foo(bar) baz] () {}; // expected-error {{called object type 'int' is not a function}}
OpenPOWER on IntegriCloud