From 463ecaca844a0a834d86b804fea9a8bed120678c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 6 Apr 2009 16:55:04 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/pt.c | 24 +++++++++++++++++++++--- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/template/fnspec1.C | 16 ++++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/fnspec1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 408625789239..02440e516e04 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2009-04-06 Jason Merrill + + 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 Jason Merrill diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3e3d4f250f28..92815c08267b 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 40b0d240ee5a..b4864a20dbb0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-04-06 Jason Merrill + + PR c++/35146 + * g++.dg/template/fnspec1.C: New. + 2009-04-06 Laurent GUERBY * 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 000000000000..5d5324475a4d --- /dev/null +++ b/gcc/testsuite/g++.dg/template/fnspec1.C @@ -0,0 +1,16 @@ +// PR c++/35146 + +template struct S {}; + +template struct ref; +template <> struct ref { typedef double result; }; + +template +void foo(typename ref::result, S*); +template <> +void foo(S, S*); // { dg-error "does not match" } +template <> +void foo(double alpha, S* x) +{ + alpha; x; +}