On Thursday, August 27th, 2026 at 6:40 PM, Jason Merrill <[email protected]> wrote:
> On 8/21/26 7:03 AM, Waffl3x wrote: > > Bootstrapped and tested on x86_64-pc-linux-gnu, okay for trunk? > > > > -- 8< -- > > > > Empty packs were not being handled correctly, but merely terminating the > > loop fails to handle a number of edge cases. This patch instead skips > > each expanded element before moving on to the next parameter to ensure > > parameters that correspond to each other are compared. It is unclear if > > merely skipping pack elements is correct but it's probably the best thing > > that can be done right now. We certainly can't test them conditionally on > > if the pack was used in a post condtion, as that would reject valid uses > > of a pack index in a post condition. > > > > PR c++/124395 > > PR c++/126837 > > > > gcc/cp/ChangeLog: > > > > * contracts.cc (check_postconditions_in_redecl): Skip packs. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/contracts/cpp26/pr124395.C: New test. > > * g++.dg/contracts/cpp26/pr126837.C: New test. > > > > Signed-off-by: Waffl3x <[email protected]> > > --- > > gcc/cp/contracts.cc | 28 +++++++++++++++++++ > > .../g++.dg/contracts/cpp26/pr124395.C | 8 ++++++ > > .../g++.dg/contracts/cpp26/pr126837.C | 9 ++++++ > > 3 files changed, 45 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/contracts/cpp26/pr124395.C > > create mode 100644 gcc/testsuite/g++.dg/contracts/cpp26/pr126837.C > > > > diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc > > index 25da963d0b4..7ca35184f30 100644 > > --- a/gcc/cp/contracts.cc > > +++ b/gcc/cp/contracts.cc > > @@ -585,6 +585,34 @@ check_postconditions_in_redecl (tree olddecl, tree > > newdecl) > > for (; t1 && t1 != void_list_node; > > t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) > > { > > + if (DECL_PACK_P (t1)) > > + { > > + /* Expanded params are checked in check_param_in_postcondition. */ > > + if (TREE_CHAIN (t1) == NULL_TREE > > + || TREE_CHAIN (t1) == void_list_node) > > + break; > > + /* Skip params that come from t1, we can't diagnose them here as they > > + might be indexed with a pack index. */ > > + const char *const pack_name = IDENTIFIER_POINTER (DECL_NAME (t1)); > > + const size_t pack_name_len = IDENTIFIER_LENGTH (DECL_NAME (t1)); > > + const auto parm_is_expanded_from_pack = [&] (const_tree expanded_id) > > + { > > + gcc_assert (TREE_CODE (expanded_id) == IDENTIFIER_NODE); > > + /* Expanded pack elements have #number added to their name. */ > > + if (!(IDENTIFIER_LENGTH (expanded_id) >= pack_name_len + 2u)) > > + return false; > > + const char *const exp_name = IDENTIFIER_POINTER (expanded_id); > > + if (strncmp (pack_name, exp_name, pack_name_len) != 0) > > + return false; > > + return exp_name[pack_name_len] == '#'; > > + }; > > Can't you use function_parameter_expanded_from_pack_p? If it didn't work I could pretend I tried it :). Jokes aside, I was hoping this did exist and couldn't find it, I'm relieved that it does. Will fix. > > > + /* Stop one node early so continuing works. */ > > + if (parm_is_expanded_from_pack (DECL_NAME (t2))) > > + while (parm_is_expanded_from_pack (DECL_NAME (TREE_CHAIN (t2)))) > > + t2 = TREE_CHAIN (t2); > > + /* Keep going to check params after the pack. */ > > + continue; > > + } > > if (parm_used_in_post_p (t1)) > > { > > set_parm_used_in_post (t2); > > diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/pr124395.C > > b/gcc/testsuite/g++.dg/contracts/cpp26/pr124395.C > > new file mode 100644 > > index 00000000000..29926a55685 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/contracts/cpp26/pr124395.C > > @@ -0,0 +1,8 @@ > > +// PR c++/124395 > > +// { dg-do compile { target c++26 } } > > +// { dg-additional-options "-fcontracts" } > > + > > +template <typename... Ts> > > +void f(Ts...) pre(true) {} > > + > > +template void f<>(); > > diff --git a/gcc/testsuite/g++.dg/contracts/cpp26/pr126837.C > > b/gcc/testsuite/g++.dg/contracts/cpp26/pr126837.C > > new file mode 100644 > > index 00000000000..a7a2b4d1253 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/contracts/cpp26/pr126837.C > > @@ -0,0 +1,9 @@ > > +// PR c++/126837 > > +// { dg-do compile { target c++26 } } > > +// { dg-additional-options "-fcontracts" } > > + > > +template<typename... Args> > > +void f(Args... args, int const a) > > + post(a) {} > > + > > +template void f<int, int>(int, int, int); > > I will also rename the test cases as discussed in other threads. Thanks for the review, Alex
