commit c51bed9b91dd53013feb770278a6e8c466001fa0 Author: Jason Merrill Date: Sat Jul 16 22:20:52 2011 -0400 * call.c (template_unification_error_rejection): Define. (add_template_candidate_real): Use it if unification caused errors. (print_z_candidate): Handle it. * pt.c (unify_template_parameter_mismatch): Remove. (unify): Use unify_expression_unequal instead. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index dc8cfe7..0279066 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -666,6 +666,12 @@ template_unification_rejection (tree tmpl, tree explicit_targs, tree targs, } static struct rejection_reason * +template_unification_error_rejection (void) +{ + return alloc_rejection (rr_template_unification); +} + +static struct rejection_reason * template_instantiation_rejection (tree tmpl, tree targs) { struct rejection_reason *r = alloc_rejection (rr_template_instantiation); @@ -2918,6 +2924,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, int i; tree fn; struct rejection_reason *reason = NULL; + int errs; /* We don't do deduction on the in-charge parameter, the VTT parameter or 'this'. */ @@ -2960,6 +2967,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, } gcc_assert (ia == nargs_without_in_chrg); + errs = errorcount+sorrycount; i = fn_type_unification (tmpl, explicit_targs, targs, args_without_in_chrg, nargs_without_in_chrg, @@ -2967,10 +2975,14 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, if (i != 0) { - reason = template_unification_rejection (tmpl, explicit_targs, - targs, args_without_in_chrg, - nargs_without_in_chrg, - return_type, strict, flags); + /* Don't repeat unification later if it already resulted in errors. */ + if (errorcount+sorrycount == errs) + reason = template_unification_rejection (tmpl, explicit_targs, + targs, args_without_in_chrg, + nargs_without_in_chrg, + return_type, strict, flags); + else + reason = template_unification_error_rejection (); goto fail; } @@ -3253,7 +3265,17 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate) r->u.conversion.to_type); break; case rr_template_unification: + /* We use template_unification_error_rejection if unification caused + actual non-SFINAE errors, in which case we don't need to repeat + them here. */ + if (r->u.template_unification.tmpl == NULL_TREE) + { + inform (loc, " substitution of deduced template arguments " + "resulted in errors seen above"); + break; + } /* Re-run template unification with diagnostics. */ + inform (loc, " template argument deduction/substitution failed:"); fn_type_unification (r->u.template_unification.tmpl, r->u.template_unification.explicit_targs, r->u.template_unification.targs, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b8d25d4..8136a99 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5464,15 +5464,6 @@ unify_template_deduction_failure (bool explain_p, tree parm, tree arg) } static int -unify_template_parameter_mismatch (bool explain_p, tree parm, tree tparm) -{ - if (explain_p) - inform (input_location, - " template parameter %qT does not match %qD", tparm, parm); - return 1; -} - -static int unify_template_argument_mismatch (bool explain_p, tree parm, tree arg) { if (explain_p) @@ -15920,7 +15911,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, int result = !(TREE_CODE (arg) == TREE_CODE (parm) && cp_tree_equal (parm, arg)); if (result) - unify_template_parameter_mismatch (explain_p, parm, tparm); + unify_expression_unequal (explain_p, parm, arg); return result; } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype29.C b/gcc/testsuite/g++.dg/cpp0x/decltype29.C index 2bb79d0..70fe441 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype29.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype29.C @@ -13,7 +13,7 @@ decltype (ft (F())) ft() {} // { dg-error "depth" } int main() { - ft(); // { dg-error "no match" } + ft(); // { dg-error "no match|wrong number" } } // { dg-prune-output "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/error4.C b/gcc/testsuite/g++.dg/cpp0x/error4.C index 29a1cdd..064c2f2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error4.C +++ b/gcc/testsuite/g++.dg/cpp0x/error4.C @@ -10,7 +10,7 @@ struct S { static U get(const volatile T&); template - static decltype(*declval()) get(...); + static decltype(*declval()) get(...); // { dg-error "operator*" } typedef decltype(get(declval())) type; // { dg-error "no match" } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C index 120dfaa..8d7d093 100644 --- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C @@ -13,5 +13,5 @@ int main() run(l); // { dg-error "no match" } // { dg-message "candidate" "candidate note" { target *-*-* } 14 } - // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 14 } + // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 5 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C index 5b8cdd9..42b48eb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C @@ -32,7 +32,7 @@ struct S { template...>::value>::type*& = enabler > - S(U...){} // # + S(U...){} // { dg-error "no type named 'type'" } }; S s(0); // { dg-error "no match" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C index 2729b31..66387b2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C @@ -21,5 +21,5 @@ struct call_sum { int main() { // This shouldn't be an error; this is bug 35722. reverse(1,2); // { dg-bogus "no match" "" { xfail *-*-* } } - // { dg-message "sorry, unimplemented" "candidate explanation" { target *-*-* } 23 } + // { dg-bogus "sorry, unimplemented" "candidate explanation" { xfail *-*-* } 6 } } diff --git a/gcc/testsuite/g++.dg/template/deduce3.C b/gcc/testsuite/g++.dg/template/deduce3.C index e8a1d4e..c5d6e00 100644 --- a/gcc/testsuite/g++.dg/template/deduce3.C +++ b/gcc/testsuite/g++.dg/template/deduce3.C @@ -4,8 +4,8 @@ void f(int, T (*)() = 0); // { dg-message "note" } void g() { typedef int A[2]; f(0); // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 6 } + // { dg-error "returning an array" "candidate explanation" { target *-*-* } 2 } typedef void F(); f(0); // { dg-error "" } - // { dg-message "candidate" "candidate note" { target *-*-* } 9 } + // { dg-error "returning a function" "candidate explanation" { target *-*-* } 2 } } diff --git a/gcc/testsuite/g++.dg/template/error45.C b/gcc/testsuite/g++.dg/template/error45.C index 454acc6..064554d 100644 --- a/gcc/testsuite/g++.dg/template/error45.C +++ b/gcc/testsuite/g++.dg/template/error45.C @@ -11,7 +11,7 @@ struct enable_if< true, T > template < typename T > struct enable_if< true, T >::type -f( T x ); +f( T x ); // { dg-error "not a class type" } void g( void ) diff --git a/gcc/testsuite/g++.dg/template/ptrmem2.C b/gcc/testsuite/g++.dg/template/ptrmem2.C index 1919047..5f03580 100644 --- a/gcc/testsuite/g++.dg/template/ptrmem2.C +++ b/gcc/testsuite/g++.dg/template/ptrmem2.C @@ -7,7 +7,7 @@ struct A {}; -template T A::* Foo (); // { dg-message "note" } +template T A::* Foo (); // { dg-error "reference" } void Baz () { diff --git a/gcc/testsuite/g++.dg/template/sfinae2.C b/gcc/testsuite/g++.dg/template/sfinae2.C index e39ca6b..c9e1031 100644 --- a/gcc/testsuite/g++.dg/template/sfinae2.C +++ b/gcc/testsuite/g++.dg/template/sfinae2.C @@ -8,7 +8,7 @@ template struct cl { const static int value = T; }; -template void fn (char (*) [cl::value] = 0 ); // { dg-message "note" } +template void fn (char (*) [cl::value] = 0 ); // { dg-error "zero-size array" } void foo (void) { diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash60.C b/gcc/testsuite/g++.old-deja/g++.pt/crash60.C index 1aad621..747af9b 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/crash60.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash60.C @@ -7,7 +7,7 @@ template< typename SID, class SDR > void k( SID sid, SDR* p, void (SDR::*) - ( typename SID::T ) ); // { dg-message "note" } + ( typename SID::T ) ); // { dg-error "no type named 'T'" } struct E { }; struct S { void f( int ); }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C index 0e5c034..a6f7674 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/unify6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/unify6.C @@ -19,7 +19,7 @@ template<> void fn() {} // ok, specialize A template<> void fn() {} // ok, specialize A // now make sure we moan when we really should -template void foo(T const *){} // { dg-message "note" } +template void foo(T const *){} // { dg-error "pointer to reference" } void f() {