[PATCH] c++, contracts: Fix pack expansions referring to dummy parameters [PR125645]
Wang Jinghao <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
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