On Sat, Feb 21, 2026 at 03:31:24PM +0900, Jason Merrill wrote:
> On 2/20/26 2:49 AM, Marek Polacek wrote:
> > dg.exp=reflect/* passed on x86_64-linux so far.  Ok for trunk?
> > 
> > -- >8 --
> > 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.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * g++.dg/reflect/expr11.C: Adjust dg-error.
> >     * g++.dg/reflect/expr12.C: Adjust test.
> > ---
> >   gcc/cp/reflect.cc                     | 24 ++++++++++++++++++++++--
> >   gcc/testsuite/g++.dg/reflect/expr11.C |  2 +-
> >   gcc/testsuite/g++.dg/reflect/expr12.C | 18 ++++++++++++++++++
> >   3 files changed, 41 insertions(+), 3 deletions(-)
> > 
> > diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
> > index 46355251bcd..0e9118129be 100644
> > --- a/gcc/cp/reflect.cc
> > +++ b/gcc/cp/reflect.cc
> > @@ -8108,8 +8108,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)
> >       {
> > @@ -8139,6 +8137,28 @@ 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_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;
> > +    }
> > +
> >     /* Now check the type to see if we are dealing with a consteval-only
> >        expression.  */
> >     if (!consteval_only_p (t))
> > diff --git a/gcc/testsuite/g++.dg/reflect/expr11.C 
> > b/gcc/testsuite/g++.dg/reflect/expr11.C
> > index 20af4bc07ae..9691ceb07c7 100644
> > --- a/gcc/testsuite/g++.dg/reflect/expr11.C
> > +++ b/gcc/testsuite/g++.dg/reflect/expr11.C
> > @@ -15,7 +15,7 @@ f ()
> >         constexpr auto cr = ^^int;
> >       }
> >     if constexpr (auto r = ^^int;  // { dg-error "consteval-only variable 
> > .r." }
> > -           r == ^^int);     // { dg-error "the value of .r. is not usable" 
> > }
> > +           r == ^^int);     // { dg-error "consteval-only expressions|the 
> > value of .r. is not usable" }
> 
> This change seems wrong, since the condition of an "if constexpr" is
> manifestly constant-evaluated.

Ah, of course.  So I have to handle even IF_STMT_CONSTEXPR_P specially.
Note that this walks even the discarded statement.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
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.
---
 gcc/cp/reflect.cc                     | 42 +++++++++++++++++++++++++--
 gcc/testsuite/g++.dg/reflect/expr11.C | 17 +++++++++++
 gcc/testsuite/g++.dg/reflect/expr12.C | 18 ++++++++++++
 3 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 522b7c06a29..2a62ea7217f 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -8112,8 +8112,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)
     {
@@ -8143,6 +8141,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))
diff --git a/gcc/testsuite/g++.dg/reflect/expr11.C 
b/gcc/testsuite/g++.dg/reflect/expr11.C
index 20af4bc07ae..44d66947d9d 100644
--- a/gcc/testsuite/g++.dg/reflect/expr11.C
+++ b/gcc/testsuite/g++.dg/reflect/expr11.C
@@ -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." }
+    }
 }
diff --git a/gcc/testsuite/g++.dg/reflect/expr12.C 
b/gcc/testsuite/g++.dg/reflect/expr12.C
index a59a60f03a3..34aed536429 100644
--- a/gcc/testsuite/g++.dg/reflect/expr12.C
+++ b/gcc/testsuite/g++.dg/reflect/expr12.C
@@ -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" }
     }
 }

base-commit: ad5905160560d1abecfb90e10bcafbf19361649a
-- 
2.53.0

Reply via email to