summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-04-06 16:55:04 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-04-06 16:55:04 -0400
commit463ecaca844a0a834d86b804fea9a8bed120678c (patch)
tree288125d2703e3ee1ec38844d785486bf035c7f63
parentb6837b94d9916498b79b854728187361dde113a0 (diff)
downloadgcc-463ecaca844a0a834d86b804fea9a8bed120678c.tar.gz
re PR c++/35146 (weird error in template function specialization)
PR c++/35146 * pt.c (fn_type_unification): For DEDUCE_EXACT check that the deduced template arguments give us the parameter types we're looking for. From-SVN: r145625
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/pt.c24
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/fnspec1.C16
4 files changed, 49 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 40862578923..02440e516e0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2009-04-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/35146
+ * pt.c (fn_type_unification): For DEDUCE_EXACT check that
+ the deduced template arguments give us the parameter types
+ we're looking for.
+
2009-04-05 Giovanni Bajo <giovannibajo@libero.it>
Jason Merrill <jason@redhat.com>
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3e3d4f250f2..92815c08267 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12301,9 +12301,27 @@ fn_type_unification (tree fn,
the corresponding deduced argument values. If the
substitution results in an invalid type, as described above,
type deduction fails. */
- if (tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE)
- == error_mark_node)
- return 1;
+ {
+ tree substed = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
+ if (substed == error_mark_node)
+ return 1;
+
+ /* If we're looking for an exact match, check that what we got
+ is indeed an exact match. It might not be if some template
+ parameters are used in non-deduced contexts. */
+ if (strict == DEDUCE_EXACT)
+ {
+ tree sarg
+ = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
+ tree arg = args;
+ if (return_type)
+ sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
+ for (; arg && sarg;
+ arg = TREE_CHAIN (arg), sarg = TREE_CHAIN (sarg))
+ if (!same_type_p (TREE_VALUE (arg), TREE_VALUE (sarg)))
+ return 1;
+ }
+ }
return result;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 40b0d240ee5..b4864a20dbb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-04-06 Jason Merrill <jason@redhat.com>
+
+ PR c++/35146
+ * g++.dg/template/fnspec1.C: New.
+
2009-04-06 Laurent GUERBY <laurent@guerby.net>
* lib/gnat.exp: Handle multilib.
diff --git a/gcc/testsuite/g++.dg/template/fnspec1.C b/gcc/testsuite/g++.dg/template/fnspec1.C
new file mode 100644
index 00000000000..5d5324475a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/fnspec1.C
@@ -0,0 +1,16 @@
+// PR c++/35146
+
+template <typename T> struct S {};
+
+template <typename R> struct ref;
+template <> struct ref<double> { typedef double result; };
+
+template <typename T>
+void foo(typename ref<T>::result, S<T>*);
+template <>
+void foo(S<double>, S<double>*); // { dg-error "does not match" }
+template <>
+void foo(double alpha, S<double>* x)
+{
+ alpha; x;
+}