Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk/15?
-- >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>);
--
2.51.0