Bootstrapped and tested on x86_64-pc-linux-gnu, okay for trunk?
-- 8< --
This patch disables postcondition diagnostics when expanding a pack for a
PACK_INDEX_EXPR. Before an element of the pack is selected, each one is
substituted, triggering diagnostics if any element of the pack is non-const.
This is solved by simply hacking processing_postcondition off temporarily
while the pack is expanded, processing_contract_condition needs to be left
on as it might be a reference that needs to be constified.
The skipped diagnostic is then called at the end of tsubst_pack_index
instead. Some hoops have to be jumped through to get a similar location,
PACK_INDEX_EXPR should probably have a usable location, but that isn't for
this patch.
PR c++/126836
gcc/cp/ChangeLog:
* pt.cc (tsubst_pack_index): Hack processing_postcondition off for
pack expansion, call check_param_in_postcondition.
gcc/testsuite/ChangeLog:
* g++.dg/contracts/cpp26/pr126836.C: New test.
Signed-off-by: Waffl3x <[email protected]>
---
gcc/cp/pt.cc | 12 ++++++++++++
gcc/testsuite/g++.dg/contracts/cpp26/pr126836.C | 12 ++++++++++++
2 files changed, 24 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/contracts/cpp26/pr126836.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ab78bbb87c0..e8a4a040d78 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -14653,6 +14653,9 @@ static tree
tsubst_pack_index (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree pack = PACK_INDEX_PACK (t);
+ /* Don't diagnose unused pack elements during tsubst_pack_expansion. */
+ const bool old_ppc = processing_postcondition;
+ processing_postcondition = false;
if (PACK_EXPANSION_P (pack))
pack = tsubst_pack_expansion (pack, args, complain, in_decl);
else
@@ -14663,6 +14666,7 @@ tsubst_pack_index (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
gcc_assert (TREE_CODE (pack) == TREE_VEC);
pack = tsubst_tree_vec (pack, args, complain, in_decl);
}
+ processing_postcondition = old_ppc;
if (TREE_CODE (pack) == TREE_VEC && TREE_VEC_LENGTH (pack) == 0)
{
if (complain & tf_error)
@@ -14684,6 +14688,14 @@ tsubst_pack_index (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
if (TREE_CODE (t) == PACK_INDEX_TYPE)
r = cp_build_qualified_type (r, cp_type_quals (t) | cp_type_quals (r),
complain | tf_ignore_bad_quals);
+ const location_t loc = [&] ()
+ {
+ if (!EXPR_P (t) || !EXPR_P (TREE_OPERAND (t, 0)))
+ return UNKNOWN_LOCATION;
+ return EXPR_LOCATION (TREE_OPERAND (TREE_OPERAND (t, 0), 1));
+ } ();
+ /* Do the diagnostic that was skipped during pack expansion. */
+ check_param_in_postcondition (strip_contract_const_wrapper (r), loc);
return r;
}
diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/pr126836.C
b/gcc/testsuite/g++.dg/contracts/cpp26/pr126836.C
new file mode 100644
index 00000000000..73f6ce2f652
--- /dev/null
+++ b/gcc/testsuite/g++.dg/contracts/cpp26/pr126836.C
@@ -0,0 +1,12 @@
+// PR c++/126836
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fcontracts" }
+
+template<typename... Args>
+void f(Args... args)
+ post(args...[1]) {}
+
+void go()
+{
+ f<int, int const, int>(0, 0, 0);
+}
--
2.55.0