From 04b89192ace3a766a17374d5bef8fb19d9be2d7c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 5 May 2020 17:39:19 -0400 Subject: [PATCH] c++: constexpr and lambda capture [PR90212] This is the same issue as PR86429, just in potential_constant_expression_1 rather than cxx_eval_constant_expression. As in that case, when we're trying to evaluate a constant expression within a lambda, we don't have a constant closure object to refer to, but we can try to refer directly to the captured variable. gcc/cp/ChangeLog 2020-05-05 Jason Merrill PR c++/90212 * constexpr.c (potential_constant_expression_1): In a lambda function, consider a captured variable directly. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/constexpr.c | 8 +++++++- .../g++.dg/cpp0x/lambda/lambda-constexpr2.C | 13 +++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 17e24d269d2..71ca21f24e4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2020-05-05 Jason Merrill + + PR c++/90212 + * constexpr.c (potential_constant_expression_1): In a lambda + function, consider a captured variable directly. + 2020-05-05 Iain Sandoe * coroutines.cc (transform_await_wrapper): Check that we have diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 637cb746576..706d8a13d8e 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -7520,12 +7520,18 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, variable with automatic storage duration defined outside that lambda-expression, where the reference would be an odr-use. */ + + if (want_rval) + /* Since we're doing an lvalue-rvalue conversion, this might + not be an odr-use, so evaluate the variable directly. */ + return RECUR (DECL_CAPTURED_VARIABLE (t), rval); + if (flags & tf_error) { tree cap = DECL_CAPTURED_VARIABLE (t); error ("lambda capture of %qE is not a constant expression", cap); - if (!want_rval && decl_constant_var_p (cap)) + if (decl_constant_var_p (cap)) inform (input_location, "because it is used as a glvalue"); } return false; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr2.C new file mode 100644 index 00000000000..b1982ab0506 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr2.C @@ -0,0 +1,13 @@ +// PR c++/90212 +// { dg-do compile { target c++11 } } + +template struct tuple { + constexpr tuple(T&& t) : t(t) { } + int t; +}; + +void foo() { + constexpr tuple v1{1}; + constexpr auto v2 = v1; + [&]{ constexpr auto v2 = v1; }; +} -- 2.30.2