]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/reflection: also walk BIND_EXPR_BODY
authorMarek Polacek <polacek@redhat.com>
Thu, 19 Feb 2026 17:40:39 +0000 (12:40 -0500)
committerMarek Polacek <polacek@redhat.com>
Wed, 25 Feb 2026 13:32:15 +0000 (08:32 -0500)
As discussed in
<https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705756.html>,
we shouldn't walk BIND_EXPR_VARS in check_out_of_consteval_use_r, but
BIND_EXPR_BODY should still be walked.

The IF_STMT is there so that we don't emit bogus errors in "if consteval"
branches, as tested in expr12.C.

gcc/cp/ChangeLog:

* reflect.cc (check_out_of_consteval_use_r): Walk BIND_EXPR_BODY.
For IF_STMT_CONSTEVAL_P, only walk the ELSE_CLAUSE.  For
IF_STMT_CONSTEXPR_P, only walk the THEN_ and ELSE_CLAUSE.

gcc/testsuite/ChangeLog:

* g++.dg/reflect/expr11.C: Test more if constexpr.
* g++.dg/reflect/expr12.C: Adjust test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/reflect.cc
gcc/testsuite/g++.dg/reflect/expr11.C
gcc/testsuite/g++.dg/reflect/expr12.C

index 5254ac028d1b8e14b54a757e7530d322876c17f9..3c82251f511b342ee8ad6db05c25b854f3fc766e 100644 (file)
@@ -8120,8 +8120,6 @@ check_out_of_consteval_use_r (tree *tp, int *walk_subtrees, void *pset)
       /* Don't walk INIT_EXPRs, because we'd emit bogus errors about
         member initializers.  */
       || TREE_CODE (t) == INIT_EXPR
-      /* Don't walk BIND_EXPR_VARS.  */
-      || TREE_CODE (t) == BIND_EXPR
       /* And don't recurse on DECL_EXPRs.  */
       || TREE_CODE (t) == DECL_EXPR)
     {
@@ -8151,6 +8149,46 @@ check_out_of_consteval_use_r (tree *tp, int *walk_subtrees, void *pset)
        return ret;
     }
 
+  if (TREE_CODE (t) == BIND_EXPR)
+    {
+      if (tree r = cp_walk_tree (&BIND_EXPR_BODY (t),
+                                check_out_of_consteval_use_r, pset,
+                                static_cast<hash_set<tree> *>(pset)))
+       return r;
+      /* Don't walk BIND_EXPR_VARS.  */
+      *walk_subtrees = false;
+      return NULL_TREE;
+    }
+
+  if (TREE_CODE (t) == IF_STMT)
+    {
+      if (IF_STMT_CONSTEVAL_P (t))
+       {
+         if (tree r = cp_walk_tree (&ELSE_CLAUSE (t),
+                                    check_out_of_consteval_use_r, pset,
+                                    static_cast<hash_set<tree> *>(pset)))
+           return r;
+         /* Don't walk the consteval branch.  */
+         *walk_subtrees = false;
+         return NULL_TREE;
+       }
+      else if (IF_STMT_CONSTEXPR_P (t))
+       {
+         if (tree r = cp_walk_tree (&THEN_CLAUSE (t),
+                                    check_out_of_consteval_use_r, pset,
+                                    static_cast<hash_set<tree> *>(pset)))
+           return r;
+         if (tree r = cp_walk_tree (&ELSE_CLAUSE (t),
+                                    check_out_of_consteval_use_r, pset,
+                                    static_cast<hash_set<tree> *>(pset)))
+           return r;
+         /* Don't walk the condition -- it's a manifestly constant-evaluated
+            context.  */
+         *walk_subtrees = false;
+         return NULL_TREE;
+       }
+    }
+
   /* Now check the type to see if we are dealing with a consteval-only
      expression.  */
   if (!consteval_only_p (t))
index 20af4bc07ae04b41349a1472d7f90c525cb5ce6b..44d66947d9d665482a7ba88976180e0e54721860 100644 (file)
@@ -29,4 +29,21 @@ f ()
     while (^^char != ^^char);
     do {} while (^^char != ^^char);
   }
+
+  if constexpr (true)
+    {
+      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+    }
+  else
+    {
+      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+    }
+  if constexpr (false)
+    {
+      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+    }
+  else
+    {
+      auto r = ^^int; // { dg-error "consteval-only variable .r." }
+    }
 }
index a59a60f03a38a861e04b0c093c8a0defd0de7759..34aed536429caeeda4203cd137d9f7088534edcc 100644 (file)
@@ -20,11 +20,29 @@ f ()
   if not consteval
     {
       ^^void;  // { dg-error "consteval-only expressions" }
+    }
+  if not consteval
+    {
       q;  // { dg-error "consteval-only expressions" }
+    }
+  if not consteval
+    {
       auto r = ^^int;  // { dg-error "consteval-only variable" }
+    }
+  if not consteval
+    {
       if (q != ^^char);  // { dg-error "consteval-only expressions" }
+    }
+  if not consteval
+    {
       if (^^char == ^^char);  // { dg-error "consteval-only expressions" }
+    }
+  if not consteval
+    {
       while (^^char != ^^char);  // { dg-error "consteval-only expressions" }
+    }
+  if not consteval
+    {
       do {} while (^^char != ^^char);  // { dg-error "consteval-only expressions" }
     }
 }