On Fri, Jan 25, 2019 at 9:18 PM Alexandre Oliva <[email protected]> wrote:
> On Jan 24, 2019, Jason Merrill <[email protected]> wrote:
>
> > The latter; you can't have a partial specialization in a function.
>
> *nod* (though not entirely reflected in the patch below, I see)
> >> Any suggestion of a good name for the inline function (or would you
> >> prefer it to be a macro?) that tests whether a decl satisfies this
> >> predicate? primary_or_partial_spec_p?
>
> > Sounds good.
>
> I was not entirely clear on what the predicate was supposed to be when I
> wrote the above. I hadn't fully realized we were testing properties of
> a template instantiation by inspecting mostly properties of the
> template, rather than of the instantiation proper. Once I realized
> that, I hesitated between introducing a function to test properties of
> the base template directly, or a function to test the instantiation for
> those properties. It wasn't clear to me that having e.g. only
> DECL_TI_TEMPLATE as an argument would be enough to test everything we
> needed: we wouldn't have the context (should be the same) or the
> template args (certainly not the same, but sharing the same depth?) of
> the instantiation we were supposed to assess to begin with.
>
> So I went with a different name that reflected more closely the test I
> implemented: instantiates_primary_template_p.
That sounds good.
> Now, maybe we're better off with something that tests the template
> rather than the instantiation, to use at other places where
> PRIMARY_TEMPLATE_P is found insufficient. If that's the case, I'll have
> to figure out whether taking just the template is enough, or whether we
> need the tinfo object or are better off taking additional arguments.
> But since that will take additional investigation and you had nodded to
> the logic that involved the args of the instantiation, I'm leaving it at
> this for now. Please let me know whether the alternate form would be
> preferred.
>
> This patch bootstrapped on x86_64- and i686-linux-gnu, and is undergoing
> regression testing ATM. Ok to install if it passes?
>
>
> 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 | 55
> +++++++++++++++++++++++++++++++++++++++-
> gcc/testsuite/g++.dg/pr87770.C | 11 ++++++++
> 2 files changed, 65 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 48c180cc13b3..d413fa81c59e 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -400,6 +400,59 @@ 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;
> + if (!DECL_P (node))
> + tinfo = CLASSTYPE_TEMPLATE_INFO (node);
> + else if (DECL_LANG_SPECIFIC (node))
> + tinfo = DECL_TEMPLATE_INFO (node);
> + else
> + tinfo = NULL_TREE;
Maybe use get_template_info?
> + 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. ??? How do we
> + tell apart a partial from a full explicit specialization in a
> + non-template context? */
We don't need to tell them apart here, the caller checks if there are
any dependent template arguments.
> + tree ctxt;
> + if (!DECL_P (node))
> + ctxt = TYPE_CONTEXT (node);
> + else
> + ctxt = DECL_CONTEXT (node);
We know tmpl is a decl, so we can unconditionally take its DECL_CONTEXT.
> + tree ctinfo;
> + if (!DECL_P (ctxt))
> + ctinfo = CLASSTYPE_TEMPLATE_INFO (ctxt);
> + else if (DECL_LANG_SPECIFIC (ctxt))
> + ctinfo = DECL_TEMPLATE_INFO (ctxt);
> + else
> + ctinfo = NULL_TREE;
And you can use get_template_info here as well.
Jason