------- Comment #5 from dodji at gcc dot gnu dot org  2009-10-25 17:47 -------
Subject: Re:   New: ICE on canonical types with variadic
        templates and CRTP


During the instantiation of the base class of "derived" we are trying to
instantiate derived<T...> in the argument list of base.

lookup_template_class should find the specialization derived<a>
in the type_specialization hash table because that specialization has been
hashed when we encountered the "derived<a> instance;" declaration in main.

But the specialization is not found, leading to another derived<a> type being
created and inserted into the type_specialization - which causes type
comparison issues later.

The reason why the derived<a> specialization is not found by
lookup_template_class has to do with ARGUMENT_PACK_SELECT nodes.

At some point during pack expansion substituting in tsubst_pack_expansion
the pack argument "a" is temporarily replaced by an ARGUMENT_PACK_SELECT node.
So in type_specialization, the argument we have for the "derived"
specialization
is no more the TYPE_ARGUMENT_PACK "a", but an ARGUMENT_PACK_SELECT node that
references that TYPE_ARGUMENT_PACK.

But then we indirectly hit lookup_template_class from within
tsubst_pack_expansion
asking for the specialization of "derived" with the "a" argument. We
fail to find the specialization because we compare the TYPE_ARGUMENT_PACK "a"
with the ARGUMENT_PACK_SELECT present in the hash table.

I am testing the patch below which seems to address the issue.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 084ad1c..e80bc30 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5818,6 +5818,18 @@ template_args_equal (tree ot, tree nt)
          return 0;
       return 1;
     }
+  else if (ot && TREE_CODE (ot) == ARGUMENT_PACK_SELECT)
+    {
+      /* We get here probably because we are in the middle of substituting
+         into the pattern of a pack expansion. In that case the
+        ARGUMENT_PACK_SELECT temporarily replaces the pack argument we are
+        interested in. So we want to use the initial pack argument for
+        the comparison.  */
+      ot = ARGUMENT_PACK_SELECT_FROM_PACK (ot);
+      if (nt && TREE_CODE (nt) == ARGUMENT_PACK_SELECT)
+       nt = ARGUMENT_PACK_SELECT_FROM_PACK (nt);
+      return template_args_equal (ot, nt);
+    }
   else if (TYPE_P (nt))
     return TYPE_P (ot) && same_type_p (ot, nt);
   else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=41785

Reply via email to