diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-09-28 04:02:39 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-09-28 04:02:39 +0000 |
commit | bb13c9a49d08b56b9a8f04bd76ad3a7972bcc478 (patch) | |
tree | 65d9331fbe86ec254e57c2043d96dde642427196 /clang/test | |
parent | 45015d9796c116c97510919179efdef9f18a99db (diff) | |
download | bcm5719-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.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp | 57 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/cxx1y-init-captures.cpp | 98 | ||||
-rw-r--r-- | clang/test/PCH/cxx1y-init-captures.cpp | 28 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-lambda-expressions.cpp | 10 |
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; } (); } }; |