On 11/23/25 6:00 PM, Nathaniel Shead wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk/15?

OK.
-- >8 --

We don't generally stream the TREE_CHAIN of a DECL, as this would cause
us to unnecessarily walk into the next member in its scope chain any
time it was referenced by an expression.

Unfortunately, REQUIRES_EXPR_PARMS is a tree chain of PARM_DECLs, so we
were only ever streaming the first parameter.  This meant that when a
parameter's type could not be tsubst'd we would ICE instead of returning
false.

This patch special-cases REQUIRES_EXPR to always stream the chain of
decls in its first operand.  As a drive-by improvement we also remove a
fixme about checking uncontexted PARM_DECLs.

        PR c++/122789

gcc/cp/ChangeLog:

        * module.cc (trees_out::core_vals): Treat REQUIRES_EXPR
        specially and stream the chained decls of its first operand.
        (trees_in::core_vals): Likewise.
        (trees_out::tree_node): Check the PARM_DECLs we see are what we
        expect.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/concept-12_a.C: New test.
        * g++.dg/modules/concept-12_b.C: New test.

Signed-off-by: Nathaniel Shead <[email protected]>
---
  gcc/cp/module.cc                            | 37 ++++++++++++++-------
  gcc/testsuite/g++.dg/modules/concept-12_a.C |  6 ++++
  gcc/testsuite/g++.dg/modules/concept-12_b.C |  5 +++
  3 files changed, 36 insertions(+), 12 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/concept-12_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/concept-12_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index a78d452ee8a..92449286a84 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -6460,13 +6460,19 @@ trees_out::core_vals (tree t)
        if (has_warning_spec (t))
          u (get_warning_spec (t));
- /* Walk in forward order, as (for instance) REQUIRES_EXPR has a
-         bunch of unscoped parms on its first operand.  It's safer to
-         create those in order.  */
        bool vl = TREE_CODE_CLASS (code) == tcc_vl_exp;
-      for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)
-                            : TREE_OPERAND_LENGTH (t)),
-            ix = unsigned (vl); ix != limit; ix++)
+      unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)
+                       : TREE_OPERAND_LENGTH (t));
+      unsigned ix = unsigned (vl);
+      if (code == REQUIRES_EXPR)
+       {
+         /* The first operand of a REQUIRES_EXPR is a tree chain
+            of PARM_DECLs.  We need to stream this separately as
+            otherwise we would only stream the first one.  */
+         chained_decls (REQUIRES_EXPR_PARMS (t));
+         ++ix;
+       }
+      for (; ix != limit; ix++)
        WT (TREE_OPERAND (t, ix));
      }
    else
@@ -7045,9 +7051,15 @@ trees_in::core_vals (tree t)
        put_warning_spec (t, u ());
bool vl = TREE_CODE_CLASS (code) == tcc_vl_exp;
-      for (unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)
-                            : TREE_OPERAND_LENGTH (t)),
-            ix = unsigned (vl); ix != limit; ix++)
+      unsigned limit = (vl ? VL_EXP_OPERAND_LENGTH (t)
+                       : TREE_OPERAND_LENGTH (t));
+      unsigned ix = unsigned (vl);
+      if (code == REQUIRES_EXPR)
+       {
+         REQUIRES_EXPR_PARMS (t) = chained_decls ();
+         ++ix;
+       }
+      for (; ix != limit; ix++)
        RTU (TREE_OPERAND (t, ix));
      }
@@ -10200,9 +10212,10 @@ trees_out::tree_node (tree t)
              break;
case PARM_DECL:
-             /* REQUIRES_EXPRs have a tree list of uncontexted
-                PARM_DECLS.  It'd be nice if they had a
-                distinguishing flag to double check.  */
+             /* REQUIRES_EXPRs have a chain of uncontexted PARM_DECLS,
+                and an implicit this parm in an NSDMI has no context.  */
+             gcc_checking_assert (CONSTRAINT_VAR_P (t)
+                                  || DECL_NAME (t) == this_identifier);
              break;
case TYPE_DECL:
diff --git a/gcc/testsuite/g++.dg/modules/concept-12_a.C 
b/gcc/testsuite/g++.dg/modules/concept-12_a.C
new file mode 100644
index 00000000000..9d370d35bab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-12_a.C
@@ -0,0 +1,6 @@
+// PR c++/122789
+// { dg-additional-options "-fmodules -fconcepts" }
+// { dg-module-cmi M }
+
+export module M;
+template <typename T> constexpr bool b = requires(int, typename T::U x) { x; };
diff --git a/gcc/testsuite/g++.dg/modules/concept-12_b.C 
b/gcc/testsuite/g++.dg/modules/concept-12_b.C
new file mode 100644
index 00000000000..83353caeacc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-12_b.C
@@ -0,0 +1,5 @@
+// PR c++/122789
+// { dg-additional-options "-fmodules -fconcepts" }
+
+module M;
+static_assert(!b<int>);

Reply via email to