[gcc/devel/ranger] c++: constexpr and lambda capture [PR90212]

Aldy Hernandez aldyh@gcc.gnu.org
Wed Jun 17 21:06:07 GMT 2020


https://gcc.gnu.org/g:04b89192ace3a766a17374d5bef8fb19d9be2d7c

commit 04b89192ace3a766a17374d5bef8fb19d9be2d7c
Author: Jason Merrill <jason@redhat.com>
Date:   Tue May 5 17:39:19 2020 -0400

    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  <jason@redhat.com>
    
            PR c++/90212
            * constexpr.c (potential_constant_expression_1): In a lambda
            function, consider a captured variable directly.

Diff:
---
 gcc/cp/ChangeLog                                      |  6 ++++++
 gcc/cp/constexpr.c                                    |  8 +++++++-
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-constexpr2.C | 13 +++++++++++++
 3 files changed, 26 insertions(+), 1 deletion(-)

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  <jason@redhat.com>
+
+	PR c++/90212
+	* constexpr.c (potential_constant_expression_1): In a lambda
+	function, consider a captured variable directly.
+
 2020-05-05  Iain Sandoe  <iain@sandoe.co.uk>
 
 	* 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<typename T> struct tuple {
+    constexpr tuple(T&& t) : t(t) { }
+    int t;
+};
+
+void foo() {
+    constexpr tuple<int> v1{1};
+    constexpr auto v2 = v1;
+    [&]{ constexpr auto v2 = v1; };
+}


More information about the Gcc-cvs mailing list