c++: Endless loop with targ deduction in member tmpl [PR95888]
My r10-7007 patch tweaked tsubst not to reduce the template level of
template parameters when tf_partial. That caused infinite looping in
is_specialization_of: we ended up with a class template specialization
whose TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) == t, so the second for
loop in is_specialization_of never finished.
There's a lot going on in this test, but essentially: the template fn
here has two template parameters, we call it with one explicitly
provided, the other one has to be deduced. So we'll find ourselves
in fn_type_unification which uses tf_partial when tsubsting the
*explicit* template arguments into the function type. That leads to
tsubstituting the return type, C<T>. C is a member template; its
most general template is
template<class U> template<class V> struct B<U>::C
we figure out (tsubst_template_args) that the template argument list
is <int, int>. They come from different levels, one comes from B<int>,
the other one from fn<int>.
So now we lookup_template_class to see if we have C<int, int>. We
do the
/* This is a full instantiation of a member template. Find
the partial instantiation of which this is an instance. */
TREE_VEC_LENGTH (arglist)--;
// arglist is now <int>, not <int, int>
found = tsubst (gen_tmpl, arglist, complain, NULL_TREE);
TREE_VEC_LENGTH (arglist)++;
magic which is looking for the partial instantiation, in this case,
that would be template<class V> struct B<int>::C. Note we're still
in a tf_partial context! So the tsubst_template_args in the tsubst
(which tries to substitute <int> into <U, V>) returns <int, V>, but
V's template level hasn't been reduced! After tsubst_template_args,
tsubst_template_decl looks to see if we already have this specialization:
// t = template_decl C
// full_args = <int, V>
spec = retrieve_specialization (t, full_args, hash);
but doesn't find the one we created a while ago, when processing
B<int> b; in the test, because V's levels don't match. Whereupon
tsubst_template_decl creates a new TEMPLATE_DECL, one that leads to
the infinite looping problem.
Fixed by using tf_none when looking for an existing partial instantiation.
It also occurred to me that I should be able to trigger a similar
problem with 'auto', since r10-7007 removed an is_auto check. And lo,
I constructed deduce10.C which exhibits the same issue with pre-r10-7007
compilers. This patch fixes that problem as well. I'm ecstatic.
gcc/cp/ChangeLog:
PR c++/95888
* pt.c (lookup_template_class_1): Pass tf_none to tsubst when looking
for the partial instantiation.
gcc/testsuite/ChangeLog:
PR c++/95888
* g++.dg/template/deduce10.C: New test.
* g++.dg/template/deduce9.C: New test.