]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: value dependence of by-ref lambda capture [PR108975]
authorPatrick Palka <ppalka@redhat.com>
Tue, 25 Apr 2023 19:59:22 +0000 (15:59 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 20 Dec 2023 01:52:10 +0000 (20:52 -0500)
We are still ICEing on the generic lambda version of the testcase from
this PR, even after r13-6743-g6f90de97634d6f, due to the by-ref capture
of the constant local variable 'dim' being considered value-dependent
when regenerating the lambda (at which point processing_template_decl is
set since the lambda is generic), which prevents us from constant folding
its uses.  Later during prune_lambda_captures we end up not thoroughly
walking the body of the lambda and overlook the (non-folded) uses of
'dim' within the array bound and using-decls.

We could fix this by making prune_lambda_captures walk the body of the
lambda more thoroughly so that it finds these uses of 'dim', but ideally
we should be able to constant fold all uses of 'dim' ahead of time and
prune the implicit capture after all.

To that end this patch makes value_dependent_expression_p return false
for such by-ref captures of constant local variables, allowing their
uses to get constant folded ahead of time.  It seems we just need to
disable the predicate's conservative early exit for reference variables
(added by r5-5022-g51d72abe5ea04e) when DECL_HAS_VALUE_EXPR_P.  This
effectively makes us treat by-value and by-ref captures more consistently
when it comes to value dependence.

PR c++/108975

gcc/cp/ChangeLog:

* pt.cc (value_dependent_expression_p) <case VAR_DECL>:
Suppress conservative early exit for reference variables
when DECL_HAS_VALUE_EXPR_P.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/lambda/lambda-const11a.C: New test.

(cherry picked from commit 3d674e29d7f89bf93fcfcc963ff0248c6347586d)

gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11a.C [new file with mode: 0644]

index f056a4f38e64dcfcb2773d961bc81416a101ac5d..adaaa8f89a69dcb0f6bdad0e696e1e9d4977c080 100644 (file)
@@ -27972,9 +27972,7 @@ value_dependent_expression_p (tree expression)
     case VAR_DECL:
        /* A constant with literal type and is initialized
          with an expression that is value-dependent.  */
-      if (DECL_DEPENDENT_INIT_P (expression)
-         /* FIXME cp_finish_decl doesn't fold reference initializers.  */
-         || TYPE_REF_P (TREE_TYPE (expression)))
+      if (DECL_DEPENDENT_INIT_P (expression))
        return true;
       if (DECL_HAS_VALUE_EXPR_P (expression))
        {
@@ -27989,6 +27987,9 @@ value_dependent_expression_p (tree expression)
                  && value_expr == error_mark_node))
            return true;
        }
+      else if (TYPE_REF_P (TREE_TYPE (expression)))
+       /* FIXME cp_finish_decl doesn't fold reference initializers.  */
+       return true;
       /* We have a constexpr variable and we're processing a template.  When
         there's lifetime extension involved (for which finish_compound_literal
         used to create a temporary), we'll not be able to evaluate the
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11a.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const11a.C
new file mode 100644 (file)
index 0000000..7fc3d48
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/108975
+// A version of lambda-const11.C using a generic lambda.
+// { dg-do compile { target c++14 } }
+
+template<int> void g();
+template<int> struct A { };
+
+template<class T>
+void f() {
+  constexpr int dim = 1;
+  auto l = [&](auto) {
+    int n[dim * 1];
+    using ty1 = decltype(g<dim * 2>());
+    using ty2 = A<dim * 3>;
+  };
+  l(0);
+  // In f<int>, we shouldn't actually capture dim.
+  static_assert (sizeof(l) == 1, "");
+}
+
+template void f<int>();