On Jan 29, 2019, Alexandre Oliva <aol...@redhat.com> 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 <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                    |   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 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

Reply via email to