[Bug c++/41785] [4.5 Regression] [C++0x] ICE on canonical types with variadic templates and CRTP
dodji at redhat dot com
gcc-bugzilla@gcc.gnu.org
Sun Oct 25 17:47:00 GMT 2009
------- 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
More information about the Gcc-bugs
mailing list