Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-02-04 Thread Alexandre Oliva
On Jan 30, 2019, Paolo Carlini  wrote:

> Hi,
> On 30/01/19 17:25, Alexandre Oliva wrote:
>> +static inline bool
>> +instantiates_primary_template_p (tree node)

> I'm rather surprised by the inline:

It's (so far) a single use function, so it will likely be inlined even
without it.  But yeah, I guess it shouldn't be marked as inline, so I
dropped that.


On Jan 30, 2019, Jason Merrill  wrote:

>> * pt.c (instantiates_primary_template_p): New.
>> (type_dependent_expression_p): Use it.

> OK.

Thanks, here's what I just installed.


[PR87770] test partial specializations for type dependence

From: Alexandre Oliva 

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 9aa3c75d2d74..b8fbf4046f07 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 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.  */
 
@@ -25683,7 +25713,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 ..69eff4a786fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr87770.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+template  struct d {
+  template  d(e);
+};
+template <> template  d::d(e);
+template <> template  d::d(e) {
+  long g;
+  (void)g;
+}
+template d::d(char);


-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free! FSF Latin America board member
GNU Toolchain EngineerFree Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-30 Thread Paolo Carlini

Hi,

On 30/01/19 17:25, Alexandre Oliva wrote:

+static inline bool
+instantiates_primary_template_p (tree node)


I'm rather surprised by the inline: as a general rule, we want functions 
this size all inline? I would say that in the C++ library we don't, 
sure, not very big but already too big.


Paolo.




Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-30 Thread Jason Merrill

On 1/30/19 11:25 AM, Alexandre Oliva wrote:

On Jan 30, 2019, Jason Merrill  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 

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.


OK.

Jason



Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-30 Thread Alexandre Oliva
On Jan 30, 2019, Jason Merrill  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 

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 0..69eff4a786fef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr87770.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+template  struct d {
+  template  d(e);
+};
+template <> template  d::d(e);
+template <> template  d::d(e) {
+  long g;
+  (void)g;
+}
+template d::d(char);


-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free! FSF Latin America board member
GNU Toolchain EngineerFree Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-29 Thread Jason Merrill
On Mon, Jan 28, 2019 at 11:37 PM Alexandre Oliva  wrote:
> On Jan 27, 2019, Jason Merrill  wrote:
>
> >> + ??? 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.
>
> The single caller does, indeed, but the function does not make that a
> requirement, so others might call it and fail to check it.  Should that
> test be moved here too?

Hmm, I wouldn't expect that from a function named
"instantiates_primary_template_p".

Perhaps another function that calls instantiates_primary_template_p
and then checks for dependent innermost template args?  I'm not sure
what to call that function, perhaps decl_has_dependent_primary_targs?

> Anyhow, the question was really about the fact that the non-template
> context has no template argument depth for us to compare with.  When I
> wrote that comment, I was returning true for !ctinfo, unconditionally,
> reasoning that if NODE's context is not a template, then NODE must
> specialize some a primary template.

Right.

> But if we want partial but not full
> explicit specializations, then just having a deeper (or nonzero)
> template argument depth is not enough, is it?

See above.  Though we're not necessarily dealing with explicit
specializations at all here, what we have is a decl produced from a
template and some args, which might or might not be specialized.

> >> +  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.
>
> Does it hurt too much to keep it more general, so that it can deal with
> template class types too?

A class template also comes from a TEMPLATE_DECL; either way, tmpl is
a TEMPLATE_DECL.

Note that I'm talking about the "tmpl" variable, not "node".

Jason


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-29 Thread Alexandre Oliva
On Jan 29, 2019, Alexandre Oliva  wrote:

> The single caller does, indeed, but the function does not make that a
> requirement, so others might call it and fail to check it.  Should that
> test be moved here too?

Like this...  Regstrapped on x86_64-linux-gnu.  Ok to install?


[PR87770] test partial specializations for type dependence

From: Alexandre Oliva 

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|   46 +---
 gcc/testsuite/g++.dg/pr87770.C |   11 ++
 2 files changed, 54 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pr87770.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 48c180cc13b3b..03f14a9cbe20e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -400,6 +400,48 @@ 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))
+{
+  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;
+  if (!DECL_P (node))
+   ctxt = TYPE_CONTEXT (node);
+  else
+   ctxt = DECL_CONTEXT (node);
+
+  tree ctinfo = get_template_info (ctxt);
+
+  int cdepth;
+  if (!ctinfo)
+   cdepth = 0;
+  else
+   cdepth = TMPL_ARGS_DEPTH (TI_ARGS (ctinfo));
+
+  if (TMPL_ARGS_DEPTH (TI_ARGS (tinfo)) <= cdepth)
+   return false;
+}
+
+  return (any_dependent_template_arguments_p
+ (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo;
+}
+
 /* Subroutine of maybe_begin_member_template_processing.
Returns true if processing DECL needs us to push template parms.  */
 
@@ -25622,9 +25664,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))
- && (any_dependent_template_arguments_p
- (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)
+  if (instantiates_primary_template_p (expression))
return true;
 }
 
diff --git a/gcc/testsuite/g++.dg/pr87770.C b/gcc/testsuite/g++.dg/pr87770.C
new file mode 100644
index 0..69eff4a786fef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr87770.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+template  struct d {
+  template  d(e);
+};
+template <> template  d::d(e);
+template <> template  d::d(e) {
+  long g;
+  (void)g;
+}
+template d::d(char);


-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free! FSF Latin America board member
GNU Toolchain EngineerFree Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-28 Thread Alexandre Oliva
On Jan 27, 2019, Jason Merrill  wrote:

>> +tinfo = DECL_TEMPLATE_INFO (node);

> Maybe use get_template_info?

Neat!  But then, if we can assume node is a decl, we might as well go
straight for DECL_TEMPLATE_INFO.  I'd rather not make that assumption,
though, and allow this new function to be called for template types as
well, because you mentioned other places that used PRIMARY_TEMPLATE_P
might need the extra logic.  I don't know whether they might be dealing
with types though.

>> + ??? 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.

The single caller does, indeed, but the function does not make that a
requirement, so others might call it and fail to check it.  Should that
test be moved here too?

Anyhow, the question was really about the fact that the non-template
context has no template argument depth for us to compare with.  When I
wrote that comment, I was returning true for !ctinfo, unconditionally,
reasoning that if NODE's context is not a template, then NODE must
specialize some a primary template.  But if we want partial but not full
explicit specializations, then just having a deeper (or nonzero)
template argument depth is not enough, is it?

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

Does it hurt too much to keep it more general, so that it can deal with
template class types too?  Or is there going to be no use for that?  In
the latter case, I suppose we should document that, and then we just use
tinfo = DECL_TEMPLATE_INFO (node) above (right?)

> And you can use get_template_info here as well.

*nod*, thanks

-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free! FSF Latin America board member
GNU Toolchain EngineerFree Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-26 Thread Jason Merrill
On Fri, Jan 25, 2019 at 9:18 PM Alexandre Oliva  wrote:
> On Jan 24, 2019, Jason Merrill  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


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-25 Thread Alexandre Oliva
On Jan 24, 2019, Jason Merrill  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.

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;
+
+  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?  */
+
+  tree ctxt;
+  if (!DECL_P (node))
+ctxt = TYPE_CONTEXT (node);
+  else
+ctxt = DECL_CONTEXT (node);
+
+  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;
+
+  int cdepth;
+  if (!ctinfo)
+cdepth = 0;
+  else
+cdepth = TMPL_ARGS_DEPTH (TI_ARGS (ctinfo));
+
+  return (TMPL_ARGS_DEPTH (TI_ARGS (tinfo)) > cdepth);
+}
+
 /* Subroutine of maybe_begin_member_template_processing.
Returns true if processing DECL needs us to push template parms.  */
 
@@ -25622,7 +25675,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 ..69eff4a786fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr87770.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+template  struct d {
+  template  d(e);
+};
+template <> template  d::d(e);
+template <> template  

Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-24 Thread Jason Merrill

On 1/23/19 10:53 PM, Alexandre Oliva wrote:

On Jan 21, 2019, Jason Merrill  wrote:


"does this have its own template arguments, not just the ones from its
enclosing class?"



Perhaps compare the number of levels of template arguments of the
function to that of its enclosing context?


Is this the logic you had in mind?  Or can we assume DECL_P to always be
false at that point, because if the context has template info it must be
a class?  (I'm not sure about the context of generic lambdas)


The latter; you can't have a partial specialization in a function.  But 
you can have them at namespace scope, so still need to avoid checking 
CLASSTYPE_TI_TEMPLATE for a non-class.



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.

Jason


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-23 Thread Alexandre Oliva
On Jan 21, 2019, Jason Merrill  wrote:

> "does this have its own template arguments, not just the ones from its
> enclosing class?"

> Perhaps compare the number of levels of template arguments of the
> function to that of its enclosing context?

Is this the logic you had in mind?  Or can we assume DECL_P to always be
false at that point, because if the context has template info it must be
a class?  (I'm not sure about the context of generic lambdas)

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?

Thanks,


@@ -25622,7 +25622,17 @@ 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 ((PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
+  || (DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (expression))
+  && (DECL_P (DECL_CONTEXT (expression))
+  ? (!DECL_TI_TEMPLATE (DECL_CONTEXT (expression))
+ || (TMPL_ARGS_DEPTH (DECL_TI_ARGS (expression))
+ > TMPL_ARGS_DEPTH (DECL_TI_ARGS
+(DECL_CONTEXT (expression)
+  : (!CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (expression))
+ || (TMPL_ARGS_DEPTH (DECL_TI_ARGS (expression))
+ > TMPL_ARGS_DEPTH (CLASSTYPE_TI_ARGS
+(DECL_CONTEXT (expression
  && (any_dependent_template_arguments_p
  (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)
return true;

-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free! FSF Latin America board member
GNU Toolchain EngineerFree Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe


Re: [C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-21 Thread Jason Merrill

On 1/18/19 1:55 AM, Alexandre Oliva wrote:

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.


I guess we need a different predicate than PRIMARY_TEMPLATE_P to mean 
"does this have its own template arguments, not just the ones from its 
enclosing class?".  There are several other places that will need to be 
adjusted as well.


I don't think that PRIMARY_TEMPLATE_P || DECL_TEMPLATE_SPECIALIZATION is 
the right test, as I would expect that the latter will also be true of 
specializations that have no template arguments of their own.


Perhaps compare the number of levels of template arguments of the 
function to that of its enclosing context?


Jason


[C++ PATCH] [PR87770] test partial specializations for type dependence

2019-01-17 Thread Alexandre Oliva
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.

Regstrapped on x86_64- and i686-linux-gnu.  Ok to install?


for  gcc/cp/ChangeLog

PR c++/87770
* pt.c (type_dependent_expression_p): Check partial
specializations for taking template arguments.

for  gcc/testsuite/ChangeLog

PR c++/87770
* g++.dg/pr87770.C: New.
---
 gcc/cp/pt.c|3 ++-
 gcc/testsuite/g++.dg/pr87770.C |   11 +++
 2 files changed, 13 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 e4f76478f543..fb8993f1959e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -25607,7 +25607,8 @@ 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 ((PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression))
+  || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (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 ..69eff4a786fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr87770.C
@@ -0,0 +1,11 @@
+// { dg-do compile }
+
+template  struct d {
+  template  d(e);
+};
+template <> template  d::d(e);
+template <> template  d::d(e) {
+  long g;
+  (void)g;
+}
+template d::d(char);


-- 
Alexandre Oliva, freedom fighter   https://FSFLA.org/blogs/lxo
Be the change, be Free! FSF Latin America board member
GNU Toolchain EngineerFree Software Evangelist
Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe