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

Reply via email to