diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-21 20:10:50 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-21 20:10:50 +0000 |
commit | b2997f579a8b6552a49eab97e33c437b9251eb0a (patch) | |
tree | 73c1636810d5a9a7b8d5e9af36cd2c6ab0182eac /clang/test | |
parent | 6e19543a2a2013bd357eb15e383b435cd0cbb810 (diff) | |
download | bcm5719-llvm-b2997f579a8b6552a49eab97e33c437b9251eb0a.tar.gz bcm5719-llvm-b2997f579a8b6552a49eab97e33c437b9251eb0a.zip |
[c++20] P0780R2: Support pack-expansion of init-captures.
This permits an init-capture to introduce a new pack:
template<typename ...T> auto x = [...a = T()] { /* a is a pack */ };
To support this, the mechanism for allowing ParmVarDecls to be packs has
been extended to support arbitrary local VarDecls.
llvm-svn: 361300
Diffstat (limited to 'clang/test')
5 files changed, 125 insertions, 5 deletions
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p17.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p17.cpp new file mode 100644 index 00000000000..e2bd513aeff --- /dev/null +++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p17.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +namespace std_example { + namespace std { template<typename T> T &&move(T &); } + + void g(...); + + template <class... Args> void f(Args... args) { + auto lm = [&, args...] { return g(args...); }; + lm(); + + auto lm2 = [... xs = std::move(args)] { return g(xs...); }; + lm2(); + } +} + +template<typename ...T> constexpr int f(int k, T ...t) { + auto a = [...v = t] (bool b) mutable { + if (!b) { + ((v += 1), ...); + return (__SIZE_TYPE__)0; + } + return (v * ... * 1) + sizeof...(v); + }; + for (int i = 0; i != k; ++i) + a(false); + return a(true); +} + +static_assert(f(1, 2, 3, 4) == 3 * 4 * 5 + 3); +static_assert(f(5) == 1); + +auto q = [...x = 0] {}; // expected-error {{does not contain any unexpanded parameter packs}} + +template<typename ...T> constexpr int nested(T ...t) { + return [...a = t] { + return [a...] { + return (a + ...); + }(); + }(); +} +static_assert(nested(1, 2, 3) == 6); 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 4ae34dec3e3..028fcee5fda 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,5 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify -Wno-c++1y-extensions -// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify -Wno-c++1y-extensions -Wno-c++2a-extensions +// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -Wno-c++2a-extensions +// RUN: %clang_cc1 -fsyntax-only -std=c++2a %s -verify void print(); @@ -60,8 +61,25 @@ 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 ','}} + [...as(args)]{} (); + [as(args)...] {} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + [as...(args)]{} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + [...as{args}]{} (); + [as{args}...] {} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + [as...{args}]{} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + [...as = args]{} (); + [as = args...] {} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + [as... = args]{} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + + [&...as(args)]{} (); + [...&as(args)]{} (); // expected-error {{ellipsis in pack init-capture must appear before the name of the capture}} + + [args...] {} (); + [...args] {} (); // expected-error {{ellipsis in pack capture must appear after the name of the capture}} + + [&args...] {} (); + [...&args] {} (); // expected-error {{ellipsis in pack capture must appear after the name of the capture}} + [&...args] {} (); // expected-error {{ellipsis in pack capture must appear after the name of the capture}} } template<typename ...Args> diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp new file mode 100644 index 00000000000..4d5b6b47459 --- /dev/null +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/init-capture.cpp @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +namespace p3 { + void bar(...); + template <typename... Args> void foo(Args... args) { + (void)[... xs = args] { + bar(xs...); + }; + } + + void use() { + foo(); + foo(1); + } +} + +template<typename ...T> void f(T ...t) { + (void)[&...x = t] { + x; // expected-error {{unexpanded parameter pack 'x'}} + }; + + // Not OK: can't expand 'x' outside its scope. + weird((void)[&...x = t] { + return &x; // expected-error {{unexpanded parameter pack 'x'}} + }... // expected-error {{does not contain any unexpanded}} + ); + + // OK, capture only one 'slice' of 'x'. + weird((void)[&x = t] { + return &x; + }... + ); + + // 'x' is not expanded by the outer '...', but 'T' is. + weird((void)[&... x = t] { + return T() + &x; // expected-error {{unexpanded parameter pack 'x'}} + }... // expected-error {{does not contain any unexpanded}} + ); +} diff --git a/clang/test/FixIt/fixit-c++2a.cpp b/clang/test/FixIt/fixit-c++2a.cpp new file mode 100644 index 00000000000..c97bb7ae610 --- /dev/null +++ b/clang/test/FixIt/fixit-c++2a.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -verify -std=c++2a %s +// RUN: cp %s %t +// RUN: not %clang_cc1 -x c++ -std=c++2a -fixit %t +// RUN: %clang_cc1 -Wall -pedantic -x c++ -std=c++2a %t + +/* This is a test of the various code modification hints that only + apply in C++2a. */ +template<typename ...T> void init_capture_pack(T ...a) { + [x... = a]{}; // expected-error {{must appear before the name}} + [x = a...]{}; // expected-error {{must appear before the name}} + [...&x = a]{}; // expected-error {{must appear before the name}} + [...a]{}; // expected-error {{must appear after the name}} + [&...a]{}; // expected-error {{must appear after the name}} + [...&a]{}; // expected-error {{must appear after the name}} +} diff --git a/clang/test/SemaTemplate/sizeof-pack.cpp b/clang/test/SemaTemplate/sizeof-pack.cpp index 4b0c883a24a..274726a2315 100644 --- a/clang/test/SemaTemplate/sizeof-pack.cpp +++ b/clang/test/SemaTemplate/sizeof-pack.cpp @@ -1,7 +1,13 @@ // RUN: %clang_cc1 -std=c++11 -verify %s -// expected-no-diagnostics template<int &...Ns> int f() { return sizeof...(Ns); } template int f<>(); + +template<typename ...T> int g() { + return [...x = T()] { // expected-warning 2{{extension}} + return sizeof...(x); + }(); +} +template int g<>(); |