Hi and happy new year, this patch is to fix a compiler seg-fault as encountered 
in the following example:

template<class> struct Class1{};

template<auto...Tn> class Class2;
template<typename...V,Class1<V>...Un> class Class2<Un...>
{
    public: void apply(){}
};

Class1<bool> class1_bool;
Class1<char> class1_char;

int main()
{
    Class2<class1_bool,class1_char> class2;
    class2.apply();
}

where it ends up populating the V argument in the instantiated template at the 
class2 declaration with the unknown placeholder and the segfault is when it 
later tries to get the name for an incompletely resolved type.

The incorrect processing happens in unify_pack_expansion where it is calling 
unify_one_argument 
here(https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/cp/pt.cc;h=0ffa0b53e26a87df3ed2c7202446c68d2800db64;hb=HEAD#l24718)
 for each argument of the argument pack and recursively unifying the inner 
arguments. In this example the inner argument against V (bool/char) is set in 
targs however it is not seen as a pack argument in unify_pack_expansion because 
in the unfixed code it does not reach and link this associated pack and later 
on when processing the collected arguments to substitute it in in 
instantiate_class_template the argument has not been set as an argument pack in 
targs and it doesn't match the the template specialisation parameter which is a 
parameter pack and it falls back to the unknown placeholder.
The parameter packs are originally linked in make_pack_expansion 
here(https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/cp/pt.cc;h=0ffa0b53e26a87df3ed2c7202446c68d2800db64;hb=HEAD#l4246)
 and the change is in this tree walk so that in the example above V is chained 
to Un and after calling unify_one_argument it loops over both packs and 
extracts their associated value set in targs and puts it into it's pack 
argument collection.

Regards
Adam Ryan
From 5c60f42e1bb143b1c3752f23368cd6d926d0b598 Mon Sep 17 00:00:00 2001
From: Adam J Ryan <gcc.gnu....@ajryansolutions.co.uk>
Date: Wed, 1 Jan 2025 13:31:01 +0000
Subject: [PATCH] Add tree walk case to obtain A pack in
 <typename...A,Class<A>...B>.

For non-type parameter packs when unifying the arguments in unify_pack_expansion
it iterates over the associated packs of a param so that when it recursivly
unifies the param with the arguments it knows which targs have been populated
with parameter pack arguments that it can then collect up. This change adds a
tree walk so that in the example above it reaches ...A and adds it to the
associated packs for ...B and therefore knows it will have been set in targs
in unify_pack_expansion and processes it as per other pack arguments.

PR gcc/118265

Signed-off-by: Adam J Ryan <gcc.gnu....@ajryansolutions.co.uk>
---
 gcc/cp/pt.cc                    |  5 +++++
 gcc/testsuite/g++.dg/pr118265.C | 17 +++++++++++++++++
 2 files changed, 22 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/pr118265.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 0ffa0b53e26..22f5d4b1875 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -4012,6 +4012,11 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
 		    &find_parameter_packs_r, ppd, ppd->visited);
       return NULL_TREE;
 
+    case TEMPLATE_PARM_INDEX:
+      if (parameter_pack_p)
+        WALK_SUBTREE ( TREE_TYPE(t) );
+      return NULL_TREE;
+
     case DECL_EXPR:
       {
 	tree decl = DECL_EXPR_DECL (t);
diff --git a/gcc/testsuite/g++.dg/pr118265.C b/gcc/testsuite/g++.dg/pr118265.C
new file mode 100644
index 00000000000..00bda1b5b48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr118265.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++20 } }
+template<class> struct Class1{};
+
+template<auto...Tn> class Class2;
+template<typename...V,Class1<V>...Un> class Class2<Un...>
+{
+    public: void apply(){}
+};
+
+Class1<bool> class1_bool;
+Class1<char> class1_char;
+
+int main()
+{
+    Class2<class1_bool,class1_char> class2;
+    class2.apply();
+}
\ No newline at end of file
-- 
2.43.0

Reply via email to