Bootstrapped/regtested on x86_64-pc-linux-gnu.
-- >8 --
Contract conditions are parsed outside the function body, so
`at_function_scope_p()' is false when their parameter pack expansions
are formed. However, function parameter packs in contract conditions
should use local specializations during substitution, just as they do
within a function body.
PR c++/125645
gcc/cp/ChangeLog:
* cp-tree.h (PACK_INDEX_PARENTHESIZED_P): Fix incorrect
documentation in usage.
(PACK_EXPANSION_LOCAL_P): Update comment.
* pt.cc (make_pack_expansion): Mark function parameter pack
expansions in contract conditions as local.
gcc/testsuite/ChangeLog:
* g++.dg/contracts/cpp26/pr125645.C: New test.
Signed-off-by: Wang Jinghao <[email protected]>
---
gcc/cp/cp-tree.h | 5 +++--
gcc/cp/pt.cc | 6 +++++-
gcc/testsuite/g++.dg/contracts/cpp26/pr125645.C | 13 +++++++++++++
3 files changed, 21 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/contracts/cpp26/pr125645.C
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c73b42ed44f..5d970ea3fa7 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -454,7 +454,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
INIT_EXPR_NRV_P (in INIT_EXPR)
ATOMIC_CONSTR_MAP_INSTANTIATED_P (in ATOMIC_CONSTR)
RETURN_EXPR_LOCAL_ADDR_P (in RETURN_EXPR)
- PACK_INDEX_PARENTHESIZED_P (in PACK_INDEX_*)
MUST_NOT_THROW_NOEXCEPT_P (in MUST_NOT_THROW_EXPR)
CONSTEVAL_BLOCK_P (in STATIC_ASSERT)
LAMBDA_EXPR_CONSTEVAL_BLOCK_P (in LAMBDA_EXPR)
@@ -486,6 +485,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
MUST_NOT_THROW_THROW_P (in MUST_NOT_THROW_EXPR)
LAMBDA_EXPR_CONST_QUAL_P (in LAMBDA_EXPR)
SPLICE_EXPR_MEMBER_ACCESS_P (in SPLICE_EXPR)
+ PACK_INDEX_PARENTHESIZED_P (in PACK_INDEX_*)
2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE)
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@@ -4425,7 +4425,8 @@ struct GTY(()) lang_decl {
? &TYPE_MAX_VALUE_RAW (NODE) \
: &TREE_OPERAND ((NODE), 1))
-/* True iff this pack expansion is within a function context. */
+/* True if this pack expansion is within a function context or
+ contract conditions. */
#define PACK_EXPANSION_LOCAL_P(NODE) \
TREE_LANG_FLAG_0 (PACK_EXPANSION_CHECK (NODE))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 54a33f0be94..4b4b0ac8dea 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4451,7 +4451,11 @@ make_pack_expansion (tree arg, tsubst_flags_t complain)
}
PACK_EXPANSION_PARAMETER_PACKS (result) = parameter_packs;
- PACK_EXPANSION_LOCAL_P (result) = at_function_scope_p ();
+ /* Contract conditions are parsed outside a function body but function
+ parameter pack expansions in them must use the instantiated parameters
+ rather than dummy declarations. */
+ PACK_EXPANSION_LOCAL_P (result)
+ = at_function_scope_p () || processing_contract_condition;
if (ppd.found_extra_args_tree_p)
/* If the pattern of this pack expansion contains a subtree that has
the extra args mechanism for avoiding partial instantiation, then
diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/pr125645.C
b/gcc/testsuite/g++.dg/contracts/cpp26/pr125645.C
new file mode 100644
index 00000000000..ecc9cf853ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/contracts/cpp26/pr125645.C
@@ -0,0 +1,13 @@
+// PR c++/125645
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-fcontracts
-fcontract-evaluation-semantic=enforce" }
+// { dg-skip-if "requires hosted libstdc++ for stdc++exp" { ! hostedlib } }
+
+template<typename... Args>
+ void f (Args... args)
+ pre (((args) && ...))
+ post (((args) && ...)) {}
+
+int main () {
+ f<const bool> (true);
+}
--
2.52.0