On Jan 30, 2019, Jason Merrill <ja...@redhat.com> wrote: > Hmm, I wouldn't expect that from a function named > "instantiates_primary_template_p".
Hmm, indeed. > Perhaps another function that calls instantiates_primary_template_p > and then checks for dependent innermost template args? Does that come up as often? If not, I'll just leave that part of the test where it was. >> > We know tmpl is a decl, so we can unconditionally take its DECL_CONTEXT. > Note that I'm talking about the "tmpl" variable, not "node". Ahh, sorry, I missed that. Nice! Here's what I regstrapped overnight. Ok to install? [PR87770] test partial specializations for type dependence From: Alexandre Oliva <aol...@redhat.com> When instantiating a partial specialization of a template member function for a full specialization of a class template, we test whether the context of variables local to the partial specialization, i.e., the partial specialization itself, is dependent, and this ICEs in type_dependent_expression_p, when checking that the function type isn't type-dependent because it is not in a type-dependent scope. We shouldn't have got that far: the previous block in type_dependent_expression_p catches cases in which the function itself takes template arguments of its own, but it only did so for primary templates, not for partial specializations. This patch fixes that. for gcc/cp/ChangeLog PR c++/87770 * pt.c (instantiates_primary_template_p): New. (type_dependent_expression_p): Use it. for gcc/testsuite/ChangeLog PR c++/87770 * g++.dg/pr87770.C: New. --- gcc/cp/pt.c | 32 +++++++++++++++++++++++++++++++- gcc/testsuite/g++.dg/pr87770.C | 11 +++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/pr87770.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f8b3054533e74..a3da1f4542b72 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -400,6 +400,36 @@ template_class_depth (tree type) return depth; } +/* Return TRUE if NODE instantiates a template that has arguments of + its own, be it directly a primary template or indirectly through a + partial specializations. */ +static inline bool +instantiates_primary_template_p (tree node) +{ + tree tinfo = get_template_info (node); + if (!tinfo) + return false; + + tree tmpl = TI_TEMPLATE (tinfo); + if (PRIMARY_TEMPLATE_P (tmpl)) + return true; + + if (!DECL_TEMPLATE_SPECIALIZATION (tmpl)) + return false; + + /* So now we know we have a specialization, but it could be a full + or a partial specialization. To tell which, compare the depth of + its template arguments with those of its context. */ + + tree ctxt = DECL_CONTEXT (tmpl); + tree ctinfo = get_template_info (ctxt); + if (!ctinfo) + return true; + + return (TMPL_ARGS_DEPTH (TI_ARGS (tinfo)) + > TMPL_ARGS_DEPTH (TI_ARGS (ctinfo))); +} + /* Subroutine of maybe_begin_member_template_processing. Returns true if processing DECL needs us to push template parms. */ @@ -25622,7 +25652,7 @@ type_dependent_expression_p (tree expression) that come from the template-id; the template arguments for the enclosing class do not make it type-dependent unless they are used in the type of the decl. */ - if (PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression)) + if (instantiates_primary_template_p (expression) && (any_dependent_template_arguments_p (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression))))) return true; diff --git a/gcc/testsuite/g++.dg/pr87770.C b/gcc/testsuite/g++.dg/pr87770.C new file mode 100644 index 0000000000000..69eff4a786fef --- /dev/null +++ b/gcc/testsuite/g++.dg/pr87770.C @@ -0,0 +1,11 @@ +// { dg-do compile } + +template <typename> struct d { + template <typename e> d(e); +}; +template <> template <typename e> d<int>::d(e); +template <> template <typename e> d<int>::d(e) { + long g; + (void)g; +} +template d<int>::d(char); -- Alexandre Oliva, freedom fighter https://FSFLA.org/blogs/lxo Be the change, be Free! FSF Latin America board member GNU Toolchain Engineer Free Software Evangelist Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe