aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2019-02-05 06:11:25 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2019-02-05 06:11:25 +0000
commite1bbb0bcf74966cbd5199d6391bdef5e8f592ef1 (patch)
tree743a7747d3c6a4ce4c8fdd73e126c6da2f16539c
parentca0107a731027066b62a78d9d8c9bd0e7084b8fa (diff)
downloadgcc-e1bbb0bcf74966cbd5199d6391bdef5e8f592ef1.zip
gcc-e1bbb0bcf74966cbd5199d6391bdef5e8f592ef1.tar.gz
gcc-e1bbb0bcf74966cbd5199d6391bdef5e8f592ef1.tar.bz2
[PR87770] test partial specializations for type dependence
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. From-SVN: r268529
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c32
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/pr87770.C11
4 files changed, 53 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6c474fd..65a850f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-05 Alexandre Oliva <aoliva@redhat.com>
+
+ PR c++/87770
+ * pt.c (instantiates_primary_template_p): New.
+ (type_dependent_expression_p): Use it.
+
2019-02-01 Jason Merrill <jason@redhat.com>
PR c++/88761 - ICE with reference capture of constant.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9aa3c75..b8fbf40 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/ChangeLog b/gcc/testsuite/ChangeLog
index 14db628..8a77c00 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-02-05 Alexandre Oliva <aoliva@redhat.com>
+
+ PR c++/87770
+ * g++.dg/pr87770.C: New.
+
2019-02-04 Harald Anlauf <anlauf@gmx.de>
PR fortran/89077
diff --git a/gcc/testsuite/g++.dg/pr87770.C b/gcc/testsuite/g++.dg/pr87770.C
new file mode 100644
index 0000000..69eff4a
--- /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);