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

Reply via email to