------- 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