re PR c++/45329 (When printing a list of candidate functions, explain why each functi...
authorNathan Froyd <froydnj@codesourcery.com>
Sun, 17 Jul 2011 02:34:10 +0000 (02:34 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 17 Jul 2011 02:34:10 +0000 (22:34 -0400)
PR c++/45329
PR c++/48934
* cp-tree.h (fn_type_unification): Add `bool' parameter.
* pt.c (enum template_base_result): Define.
(unify_success, unify_unknown): Define.
(unify_parameter_deduction_failure): Define.
(unify_invalid, unify_cv_qual_mismatch, unify_type_mismatch): Define.
(unify_parameter_pack_mismatch): Define.
(unify_parameter_pack_inconsistent): Define.
(unify_ptrmem_cst_mismatch, unify_vla_arg): Define.
(unify_expression_unequal, unify_inconsistency): Define.
(unify_method_type_error, unify_arity): Likewise.
(unify_too_many_parameters, unify_too_few_parameters): Define.
(unify_arg_conversion, unify_no_common_base): Define.
(unify_illformed_ptrmem_cst_expr): Define.
(unify_substitution_failure): Define.
(unify_inconsistent_template_template_parameters): Define.
(unify_template_deduction_failure): Define.
(unify_template_argument_mismatch): Define.
(unify_overload_resolution_failure): Define.
(comp_template_args_with_info): New function, split out from...
(comp_template_args): ...here. Call it.
(deduction_tsubst_fntype): Add `complain' parameter'.  Pass it
to tsubst.
(unify): Add `explain_p' parameter.  Pass to all relevant calls.
Call above status functions when appropriate.
(resolve_overloaded_unification, try_one_overload): Likewise.
(type_unification, type_unification_real): Likewise.
(unify_pack_expansion): Likewise.
(get_template_base, try_class_unification): Likewise.
(get_bindings, more_specialized_fn): Pass false to unification
calls.
(get_class_bindings, do_auto_deduction): Likewise.
(convert_nontype_argument): Likewise.
(fn_type_unification): Likewise.  Pass tf_warning_or_error if
explain_p.
(get_template_base): Add `explain_p' parameter and pass it to
try_class_unification. Return an enum template_base_result.
* class.c (resolve_address_of_overloaded_function): Pass false to
fn_type_unification.
* call.c (enum rejection_reason_code): Add new codes.
(struct rejection_reason): Add template_unification field.
Add template_instantiation field.
(template_unification_rejection): Define.
(template_unification_error_rejection): Define.
(template_instantiation_rejection): Define.
(invalid_copy_with_fn_template_rejection): Define.
(add_template_candidate): Pass false to unify.
Provide more rejection reasons when possible.
(print_template_unification_rejection): Define.
(print_arity_rejection): Define, split out from...
(print_z_candidate): ...here.  Add cases for new rejection
reasons.

Co-Authored-By: Jason Merrill <jason@redhat.com>
From-SVN: r176365

58 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/decltype29.C
gcc/testsuite/g++.dg/cpp0x/error4.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
gcc/testsuite/g++.dg/cpp0x/nullptr15.C
gcc/testsuite/g++.dg/cpp0x/pr31431-2.C
gcc/testsuite/g++.dg/cpp0x/pr31431.C
gcc/testsuite/g++.dg/cpp0x/pr31434.C
gcc/testsuite/g++.dg/cpp0x/sfinae11.C
gcc/testsuite/g++.dg/cpp0x/sfinae26.C
gcc/testsuite/g++.dg/cpp0x/temp_default2.C
gcc/testsuite/g++.dg/cpp0x/trailing4.C
gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C
gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C
gcc/testsuite/g++.dg/cpp0x/variadic105.C
gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C
gcc/testsuite/g++.dg/ext/vla2.C
gcc/testsuite/g++.dg/other/ptrmem10.C
gcc/testsuite/g++.dg/other/ptrmem11.C
gcc/testsuite/g++.dg/overload/template5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/overload/unknown1.C
gcc/testsuite/g++.dg/template/conv11.C
gcc/testsuite/g++.dg/template/deduce3.C
gcc/testsuite/g++.dg/template/dependent-expr5.C
gcc/testsuite/g++.dg/template/error45.C
gcc/testsuite/g++.dg/template/friend.C
gcc/testsuite/g++.dg/template/incomplete2.C
gcc/testsuite/g++.dg/template/local4.C
gcc/testsuite/g++.dg/template/local6.C
gcc/testsuite/g++.dg/template/operator9.C
gcc/testsuite/g++.dg/template/overload12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/ptrmem2.C
gcc/testsuite/g++.dg/template/sfinae2.C
gcc/testsuite/g++.dg/template/ttp25.C
gcc/testsuite/g++.dg/template/unify10.C
gcc/testsuite/g++.dg/template/unify11.C
gcc/testsuite/g++.dg/template/unify6.C
gcc/testsuite/g++.dg/template/unify7.C
gcc/testsuite/g++.dg/template/unify9.C
gcc/testsuite/g++.dg/template/varmod1.C
gcc/testsuite/g++.old-deja/g++.brendan/crash56.C
gcc/testsuite/g++.old-deja/g++.pt/crash28.C
gcc/testsuite/g++.old-deja/g++.pt/crash60.C
gcc/testsuite/g++.old-deja/g++.pt/explicit41.C
gcc/testsuite/g++.old-deja/g++.pt/explicit77.C
gcc/testsuite/g++.old-deja/g++.pt/expr2.C
gcc/testsuite/g++.old-deja/g++.pt/ptrmem6.C
gcc/testsuite/g++.old-deja/g++.pt/spec5.C
gcc/testsuite/g++.old-deja/g++.pt/spec6.C
gcc/testsuite/g++.old-deja/g++.pt/unify4.C
gcc/testsuite/g++.old-deja/g++.pt/unify6.C
gcc/testsuite/g++.old-deja/g++.pt/unify8.C
gcc/testsuite/g++.old-deja/g++.robertl/eb98.C

index bb503c3b0905e81813126038c35aa9c62e7de7cf..4db0c7e89208f6606939c95278bdbde2652001cb 100644 (file)
@@ -1,3 +1,60 @@
+2011-07-16  Nathan Froyd  <froydnj@codesourcery.com>
+           Jason Merrill  <jason@redhat.com>
+
+       PR c++/45329
+       PR c++/48934
+       * cp-tree.h (fn_type_unification): Add `bool' parameter.
+       * pt.c (enum template_base_result): Define.
+       (unify_success, unify_unknown): Define.
+       (unify_parameter_deduction_failure): Define.
+       (unify_invalid, unify_cv_qual_mismatch, unify_type_mismatch): Define.
+       (unify_parameter_pack_mismatch): Define.
+       (unify_parameter_pack_inconsistent): Define.
+       (unify_ptrmem_cst_mismatch, unify_vla_arg): Define.
+       (unify_expression_unequal, unify_inconsistency): Define.
+       (unify_method_type_error, unify_arity): Likewise.
+       (unify_too_many_parameters, unify_too_few_parameters): Define.
+       (unify_arg_conversion, unify_no_common_base): Define.
+       (unify_illformed_ptrmem_cst_expr): Define.
+       (unify_substitution_failure): Define.
+       (unify_inconsistent_template_template_parameters): Define.
+       (unify_template_deduction_failure): Define.
+       (unify_template_argument_mismatch): Define.
+       (unify_overload_resolution_failure): Define.
+       (comp_template_args_with_info): New function, split out from...
+       (comp_template_args): ...here.  Call it.
+       (deduction_tsubst_fntype): Add `complain' parameter'.  Pass it
+       to tsubst.
+       (unify): Add `explain_p' parameter.  Pass to all relevant calls.
+       Call above status functions when appropriate.
+       (resolve_overloaded_unification, try_one_overload): Likewise.
+       (type_unification, type_unification_real): Likewise.
+       (unify_pack_expansion): Likewise.
+       (get_template_base, try_class_unification): Likewise.
+       (get_bindings, more_specialized_fn): Pass false to unification
+       calls.
+       (get_class_bindings, do_auto_deduction): Likewise.
+       (convert_nontype_argument): Likewise.
+       (fn_type_unification): Likewise.  Pass tf_warning_or_error if
+       explain_p.
+       (get_template_base): Add `explain_p' parameter and pass it to
+       try_class_unification.  Return an enum template_base_result.
+       * class.c (resolve_address_of_overloaded_function): Pass false to
+       fn_type_unification.
+       * call.c (enum rejection_reason_code): Add new codes.
+       (struct rejection_reason): Add template_unification field.
+       Add template_instantiation field.
+       (template_unification_rejection): Define.
+       (template_unification_error_rejection): Define.
+       (template_instantiation_rejection): Define.
+       (invalid_copy_with_fn_template_rejection): Define.
+       (add_template_candidate): Pass false to unify.
+       Provide more rejection reasons when possible.
+       (print_template_unification_rejection): Define.
+       (print_arity_rejection): Define, split out from...
+       (print_z_candidate): ...here.  Add cases for new rejection
+       reasons.
+
 2011-07-15  Jason Merrill  <jason@redhat.com>
 
        * Make-lang.in (check-g++-strict-gc): New.
index 56f3408adc6b5c86e4005bd2f6bf6a2e3f4a8df1..99f9cc3d25a55e1e1891ad873e534754cf45c54d 100644 (file)
@@ -434,7 +434,10 @@ enum rejection_reason_code {
   rr_arity,
   rr_explicit_conversion,
   rr_arg_conversion,
-  rr_bad_arg_conversion
+  rr_bad_arg_conversion,
+  rr_template_unification,
+  rr_template_instantiation,
+  rr_invalid_copy
 };
 
 struct conversion_info {
@@ -462,6 +465,24 @@ struct rejection_reason {
     struct conversion_info conversion;
     /* Same, but for bad argument conversions.  */
     struct conversion_info bad_conversion;
+    /* Information about template unification failures.  These are the
+       parameters passed to fn_type_unification.  */
+    struct {
+      tree tmpl;
+      tree explicit_targs;
+      tree targs;
+      const tree *args;
+      unsigned int nargs;
+      tree return_type;
+      unification_kind_t strict;
+      int flags;
+    } template_unification;
+    /* Information about template instantiation failures.  These are the
+       parameters passed to instantiate_template.  */
+    struct {
+      tree tmpl;
+      tree targs;
+    } template_instantiation;
   } u;
 };
 
@@ -622,6 +643,50 @@ explicit_conversion_rejection (tree from, tree to)
   return r;
 }
 
+static struct rejection_reason *
+template_unification_rejection (tree tmpl, tree explicit_targs, tree targs,
+                               const tree *args, unsigned int nargs,
+                               tree return_type, unification_kind_t strict,
+                               int flags)
+{
+  size_t args_n_bytes = sizeof (*args) * nargs;
+  tree *args1 = (tree *) conversion_obstack_alloc (args_n_bytes);
+  struct rejection_reason *r = alloc_rejection (rr_template_unification);
+  r->u.template_unification.tmpl = tmpl;
+  r->u.template_unification.explicit_targs = explicit_targs;
+  r->u.template_unification.targs = targs;
+  /* Copy args to our own storage.  */
+  memcpy (args1, args, args_n_bytes);
+  r->u.template_unification.args = args1;
+  r->u.template_unification.nargs = nargs;
+  r->u.template_unification.return_type = return_type;
+  r->u.template_unification.strict = strict;
+  r->u.template_unification.flags = flags;
+  return r;
+}
+
+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);
+  r->u.template_instantiation.tmpl = tmpl;
+  r->u.template_instantiation.targs = targs;
+  return r;
+}
+
+static struct rejection_reason *
+invalid_copy_with_fn_template_rejection (void)
+{
+  struct rejection_reason *r = alloc_rejection (rr_invalid_copy);
+  return r;
+}
+
 /* Dynamically allocate a conversion.  */
 
 static conversion *
@@ -2859,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'.  */
@@ -2901,17 +2967,31 @@ 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,
-                          return_type, strict, flags);
+                          return_type, strict, flags, false);
 
   if (i != 0)
-    goto fail;
+    {
+      /* 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;
+    }
 
   fn = instantiate_template (tmpl, targs, tf_none);
   if (fn == error_mark_node)
-    goto fail;
+    {
+      reason = template_instantiation_rejection (tmpl, targs);
+      goto fail;
+    }
 
   /* In [class.copy]:
 
@@ -2940,7 +3020,10 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
       tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
       if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
                                    ctype))
-       goto fail;
+       {
+         reason = invalid_copy_with_fn_template_rejection ();
+         goto fail;
+       }
     }
 
   if (obj != NULL_TREE)
@@ -3108,6 +3191,18 @@ print_conversion_rejection (location_t loc, struct conversion_info *info)
            info->n_arg+1, info->from_type, info->to_type);
 }
 
+/* Print information about a candidate with WANT parameters and we found
+   HAVE.  */
+
+static void
+print_arity_information (location_t loc, unsigned int have, unsigned int want)
+{
+  inform_n (loc, want,
+           "  candidate expects %d argument, %d provided",
+           "  candidate expects %d arguments, %d provided",
+           want, have);
+}
+
 /* Print information about one overload candidate CANDIDATE.  MSGSTR
    is the text to print before the candidate itself.
 
@@ -3154,10 +3249,8 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
       switch (r->code)
        {
        case rr_arity:
-         inform_n (loc, r->u.arity.expected,
-                   "  candidate expects %d argument, %d provided",
-                   "  candidate expects %d arguments, %d provided",
-                   r->u.arity.expected, r->u.arity.actual);
+         print_arity_information (loc, r->u.arity.actual,
+                                  r->u.arity.expected);
          break;
        case rr_arg_conversion:
          print_conversion_rejection (loc, &r->u.conversion);
@@ -3171,6 +3264,39 @@ print_z_candidate (const char *msgstr, struct z_candidate *candidate)
                  "conversion", r->u.conversion.from_type,
                  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,
+                              r->u.template_unification.args,
+                              r->u.template_unification.nargs,
+                              r->u.template_unification.return_type,
+                              r->u.template_unification.strict,
+                              r->u.template_unification.flags,
+                              true);
+         break;
+       case rr_template_instantiation:
+         /* Re-run template instantiation with diagnostics.  */
+         instantiate_template (r->u.template_instantiation.tmpl,
+                               r->u.template_instantiation.targs,
+                               tf_warning_or_error);
+         break;
+       case rr_invalid_copy:
+         inform (loc,
+                 "  a constructor taking a single argument of its own "
+                 "class type is invalid");
+         break;
        case rr_none:
        default:
          /* This candidate didn't have any issues or we failed to
index 7de104d4bc764ef23a56c63a806629311e6da714..61c1380d7b2203996af702b2135879b46f19e90a 100644 (file)
@@ -6570,7 +6570,7 @@ resolve_address_of_overloaded_function (tree target_type,
          targs = make_tree_vec (DECL_NTPARMS (fn));
          if (fn_type_unification (fn, explicit_targs, targs, args, nargs,
                                   target_ret_type, DEDUCE_EXACT,
-                                  LOOKUP_NORMAL))
+                                  LOOKUP_NORMAL, false))
            /* Argument deduction failed.  */
            continue;
 
index 96d9fa8e22e4c8eabbd28cc203fb3ab887483bff..c5905850ca458937cf064ec92b6522d739bc30f5 100644 (file)
@@ -5161,7 +5161,8 @@ extern tree instantiate_class_template            (tree);
 extern tree instantiate_template               (tree, tree, tsubst_flags_t);
 extern int fn_type_unification                 (tree, tree, tree,
                                                 const tree *, unsigned int,
-                                                tree, unification_kind_t, int);
+                                                tree, unification_kind_t, int,
+                                                bool);
 extern void mark_decl_instantiated             (tree, int);
 extern int more_specialized_fn                 (tree, tree, int);
 extern void do_decl_instantiation              (tree, tree);
index d50e214ddf20cd45f3b0dd6ff475ee9243bbd3ae..a93f677c8419ff0939d4efc2136ecfc3c7377d90 100644 (file)
@@ -109,15 +109,22 @@ static GTY(()) VEC(tree,gc) *canonical_template_parms;
 #define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
 #define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
 
+enum template_base_result {
+  tbr_incomplete_type,
+  tbr_ambiguous_baseclass,
+  tbr_success
+};
+
 static void push_access_scope (tree);
 static void pop_access_scope (tree);
 static void push_deduction_access_scope (tree);
 static void pop_deduction_access_scope (tree);
 static bool resolve_overloaded_unification (tree, tree, tree, tree,
-                                           unification_kind_t, int);
+                                           unification_kind_t, int,
+                                           bool);
 static int try_one_overload (tree, tree, tree, tree, tree,
-                            unification_kind_t, int, bool);
-static int unify (tree, tree, tree, tree, int);
+                            unification_kind_t, int, bool, bool);
+static int unify (tree, tree, tree, tree, int, bool);
 static void add_pending_template (tree);
 static tree reopen_tinst_level (struct tinst_level *);
 static tree tsubst_initializer_list (tree, tree);
@@ -131,7 +138,8 @@ static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
                                             tree);
 static int type_unification_real (tree, tree, tree, const tree *,
-                                 unsigned int, int, unification_kind_t, int);
+                                 unsigned int, int, unification_kind_t, int,
+                                 bool);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
 static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
@@ -156,7 +164,8 @@ static tree get_bindings (tree, tree, tree, bool);
 static int template_decl_level (tree);
 static int check_cv_quals_for_unify (int, tree, tree);
 static void template_parm_level_and_index (tree, int*, int*);
-static int unify_pack_expansion (tree, tree, tree, tree, int, bool, bool);
+static int unify_pack_expansion (tree, tree, tree,
+                                tree, int, bool, bool, bool);
 static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
@@ -168,8 +177,9 @@ static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
 static bool check_specialization_scope (void);
 static tree process_partial_specialization (tree);
 static void set_current_access_from_decl (tree);
-static tree get_template_base (tree, tree, tree, tree);
-static tree try_class_unification (tree, tree, tree, tree);
+static enum template_base_result get_template_base (tree, tree, tree, tree,
+                                                   bool , tree *);
+static tree try_class_unification (tree, tree, tree, tree, bool);
 static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
                                           tree, tree);
 static bool template_template_parm_bindings_ok_p (tree, tree);
@@ -5267,6 +5277,211 @@ has_value_dependent_address (tree op)
   return false;
 }
 
+/* The next set of functions are used for providing helpful explanatory
+   diagnostics for failed overload resolution.  Their messages should be
+   indented by two spaces for consistency with the messages in
+   call.c  */
+
+static int
+unify_success (bool explain_p ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+static int
+unify_parameter_deduction_failure (bool explain_p, tree parm)
+{
+  if (explain_p)
+    inform (input_location,
+           "  couldn't deduce template parameter %qD", parm);
+  return 1;
+}
+
+static int
+unify_invalid (bool explain_p ATTRIBUTE_UNUSED)
+{
+  return 1;
+}
+
+static int
+unify_cv_qual_mismatch (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  types %qT and %qT have incompatible cv-qualifiers",
+           parm, arg);
+  return 1;
+}
+
+static int
+unify_type_mismatch (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location, "  mismatched types %qT and %qT", parm, arg);
+  return 1;
+}
+
+static int
+unify_parameter_pack_mismatch (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  template parameter %qD is not a parameter pack, but "
+           "argument %qD is",
+           parm, arg);
+  return 1;
+}
+
+static int
+unify_ptrmem_cst_mismatch (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  template argument %qE does not match "
+           "pointer-to-member constant %qE",
+           arg, parm);
+  return 1;
+}
+
+static int
+unify_expression_unequal (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location, "  %qE is not equivalent to %qE", parm, arg);
+  return 1;
+}
+
+static int
+unify_parameter_pack_inconsistent (bool explain_p, tree old_arg, tree new_arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  inconsistent parameter pack deduction with %qT and %qT",
+           old_arg, new_arg);
+  return 1;
+}
+
+static int
+unify_inconsistency (bool explain_p, tree parm, tree first, tree second)
+{
+  if (explain_p)
+    inform (input_location,
+           "  deduced conflicting types for parameter %qT (%qT and %qT)",
+           parm, first, second);
+  return 1;
+}
+
+static int
+unify_vla_arg (bool explain_p, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  variable-sized array type %qT is not "
+           "a valid template argument",
+           arg);
+  return 1;
+}
+
+static int
+unify_method_type_error (bool explain_p, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  member function type %qT is not a valid template argument",
+           arg);
+  return 1;
+}
+
+static int
+unify_arity (bool explain_p, int have, int wanted)
+{
+  if (explain_p)
+    inform_n (input_location, wanted,
+             "  candidate expects %d argument, %d provided",
+             "  candidate expects %d arguments, %d provided",
+             wanted, have);
+  return 1;
+}
+
+static int
+unify_too_many_arguments (bool explain_p, int have, int wanted)
+{
+  return unify_arity (explain_p, have, wanted);
+}
+
+static int
+unify_too_few_arguments (bool explain_p, int have, int wanted)
+{
+  return unify_arity (explain_p, have, wanted);
+}
+
+static int
+unify_arg_conversion (bool explain_p, tree to_type,
+                     tree from_type, tree arg)
+{
+  if (explain_p)
+    inform (input_location, "  cannot convert %qE (type %qT) to type %qT",
+           arg, from_type, to_type);
+  return 1;
+}
+
+static int
+unify_no_common_base (bool explain_p, enum template_base_result r,
+                     tree parm, tree arg)
+{
+  if (explain_p)
+    switch (r)
+      {
+      case tbr_ambiguous_baseclass:
+       inform (input_location, "  %qT is an ambiguous base class of %qT",
+               arg, parm);
+       break;
+      default:
+       inform (input_location, "  %qT is not derived from %qT", arg, parm);
+       break;
+      }
+  return 1;
+}
+
+static int
+unify_inconsistent_template_template_parameters (bool explain_p)
+{
+  if (explain_p)
+    inform (input_location,
+           "  template parameters of a template template argument are "
+           "inconsistent with other deduced template arguments");
+  return 1;
+}
+
+static int
+unify_template_deduction_failure (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  can't deduce a template for %qT from non-template type %qT",
+           parm, arg);
+  return 1;
+}
+
+static int
+unify_template_argument_mismatch (bool explain_p, tree parm, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  template argument %qE does not match %qD", arg, parm);
+  return 1;
+}
+
+static int
+unify_overload_resolution_failure (bool explain_p, tree arg)
+{
+  if (explain_p)
+    inform (input_location,
+           "  could not resolve address from overloaded function %qE",
+           arg);
+  return 1;
+}
+
 /* Attempt to convert the non-type template parameter EXPR to the
    indicated TYPE.  If the conversion is successful, return the
    converted value.  If the conversion is unsuccessful, return
@@ -6550,11 +6765,13 @@ template_args_equal (tree ot, tree nt)
     return cp_tree_equal (ot, nt);
 }
 
-/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
-   of template arguments.  Returns 0 otherwise.  */
+/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets of
+   template arguments.  Returns 0 otherwise, and updates OLDARG_PTR and
+   NEWARG_PTR with the offending arguments if they are non-NULL.  */
 
-int
-comp_template_args (tree oldargs, tree newargs)
+static int
+comp_template_args_with_info (tree oldargs, tree newargs,
+                             tree *oldarg_ptr, tree *newarg_ptr)
 {
   int i;
 
@@ -6567,11 +6784,26 @@ comp_template_args (tree oldargs, tree newargs)
       tree ot = TREE_VEC_ELT (oldargs, i);
 
       if (! template_args_equal (ot, nt))
-       return 0;
+       {
+         if (oldarg_ptr != NULL)
+           *oldarg_ptr = ot;
+         if (newarg_ptr != NULL)
+           *newarg_ptr = nt;
+         return 0;
+       }
     }
   return 1;
 }
 
+/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets
+   of template arguments.  Returns 0 otherwise.  */
+
+int
+comp_template_args (tree oldargs, tree newargs)
+{
+  return comp_template_args_with_info (oldargs, newargs, NULL, NULL);
+}
+
 static void
 add_pending_template (tree d)
 {
@@ -13724,7 +13956,7 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
    This is, of course, not reentrant.  */
 
 static tree
-deduction_tsubst_fntype (tree fn, tree targs)
+deduction_tsubst_fntype (tree fn, tree targs, tsubst_flags_t complain)
 {
   static bool excessive_deduction_depth;
   static int deduction_depth;
@@ -13748,7 +13980,7 @@ deduction_tsubst_fntype (tree fn, tree targs)
   input_location = DECL_SOURCE_LOCATION (fn);
   ++deduction_depth;
   push_deduction_access_scope (fn);
-  r = tsubst (fntype, targs, tf_none, NULL_TREE);
+  r = tsubst (fntype, targs, complain, NULL_TREE);
   pop_deduction_access_scope (fn);
   --deduction_depth;
 
@@ -13961,7 +14193,8 @@ fn_type_unification (tree fn,
                     unsigned int nargs,
                     tree return_type,
                     unification_kind_t strict,
-                    int flags)
+                    int flags,
+                    bool explain_p)
 {
   tree parms;
   tree fntype;
@@ -13996,12 +14229,15 @@ fn_type_unification (tree fn,
       bool incomplete = false;
 
       if (explicit_targs == error_mark_node)
-       return 1;
+       return unify_invalid (explain_p);
 
       converted_args
-       = (coerce_template_parms (tparms, explicit_targs, NULL_TREE, tf_none,
-                                 /*require_all_args=*/false,
-                                 /*use_default_args=*/false));
+       = (coerce_template_parms (tparms, explicit_targs, NULL_TREE,
+                                 (explain_p
+                                  ? tf_warning_or_error
+                                  : tf_none),
+                                  /*require_all_args=*/false,
+                                  /*use_default_args=*/false));
       if (converted_args == error_mark_node)
        return 1;
 
@@ -14060,7 +14296,10 @@ fn_type_unification (tree fn,
         incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
 
       processing_template_decl += incomplete;
-      fntype = deduction_tsubst_fntype (fn, converted_args);
+      fntype = deduction_tsubst_fntype (fn, converted_args,
+                                       (explain_p
+                                        ? tf_warning_or_error
+                                        : tf_none));
       processing_template_decl -= incomplete;
 
       if (fntype == error_mark_node)
@@ -14092,7 +14331,7 @@ fn_type_unification (tree fn,
      event.  */
   result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
                                  targs, parms, args, nargs, /*subr=*/0,
-                                 strict, flags);
+                                 strict, flags, explain_p);
 
   /* Now that we have bindings for all of the template arguments,
      ensure that the arguments deduced for the template template
@@ -14118,7 +14357,7 @@ fn_type_unification (tree fn,
   if (result == 0
       && !template_template_parm_bindings_ok_p 
            (DECL_INNERMOST_TEMPLATE_PARMS (fn), targs))
-    return 1;
+    return unify_inconsistent_template_template_parameters (explain_p);
 
   if (result == 0)
     /* All is well so far.  Now, check:
@@ -14131,7 +14370,10 @@ fn_type_unification (tree fn,
        substitution results in an invalid type, as described above,
        type deduction fails.  */
     {
-      tree substed = deduction_tsubst_fntype (fn, targs);
+      tree substed = deduction_tsubst_fntype (fn, targs,
+                                             (explain_p
+                                              ? tf_warning_or_error
+                                              : tf_none));
       if (substed == error_mark_node)
        return 1;
 
@@ -14148,7 +14390,8 @@ fn_type_unification (tree fn,
            sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
          for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
            if (!same_type_p (args[i], TREE_VALUE (sarg)))
-             return 1;
+             return unify_type_mismatch (explain_p, args[i],
+                                         TREE_VALUE (sarg));
        }
     }
 
@@ -14279,7 +14522,8 @@ type_unification_real (tree tparms,
                       unsigned int xnargs,
                       int subr,
                       unification_kind_t strict,
-                      int flags)
+                      int flags,
+                      bool explain_p)
 {
   tree parm, arg, arg_expr;
   int i;
@@ -14350,7 +14594,7 @@ type_unification_real (tree tparms,
       arg_expr = NULL;
 
       if (arg == error_mark_node)
-       return 1;
+       return unify_invalid (explain_p);
       if (arg == unknown_type_node)
        /* We can't deduce anything from this, but we might get all the
           template args from other function args.  */
@@ -14376,7 +14620,10 @@ type_unification_real (tree tparms,
                                  flags))
            continue;
 
-         return 1;
+         if (strict == DEDUCE_EXACT)
+           return unify_type_mismatch (explain_p, parm, arg);
+         else
+           return unify_arg_conversion (explain_p, parm, type, arg);
        }
 
       if (!TYPE_P (arg))
@@ -14392,15 +14639,15 @@ type_unification_real (tree tparms,
                 function templates and at most one of a set of
                 overloaded functions provides a unique match.  */
              if (resolve_overloaded_unification
-                 (tparms, targs, parm, arg, strict, sub_strict))
+                 (tparms, targs, parm, arg, strict, sub_strict, explain_p))
                continue;
 
-             return 1;
+             return unify_overload_resolution_failure (explain_p, arg);
            }
          arg_expr = arg;
          arg = unlowered_expr_type (arg);
          if (arg == error_mark_node)
-           return 1;
+           return unify_invalid (explain_p);
        }
 
       {
@@ -14412,7 +14659,9 @@ type_unification_real (tree tparms,
 
        if (arg == init_list_type_node && arg_expr)
          arg = arg_expr;
-       if (unify (tparms, targs, parm, arg, arg_strict))
+       if (unify (tparms, targs, parm, arg, arg_strict, explain_p))
+         /* If unification failed, the recursive call will have updated
+            UI appropriately.  */
          return 1;
       }
     }
@@ -14434,7 +14683,7 @@ type_unification_real (tree tparms,
       /* Copy the parameter into parmvec.  */
       TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
       if (unify_pack_expansion (tparms, targs, parmvec, argvec, strict,
-                                /*call_args_p=*/true, /*subr=*/subr))
+                                /*call_args_p=*/true, /*subr=*/subr, explain_p))
         return 1;
 
       /* Advance to the end of the list of parameters.  */
@@ -14444,11 +14693,20 @@ type_unification_real (tree tparms,
   /* Fail if we've reached the end of the parm list, and more args
      are present, and the parm list isn't variadic.  */
   if (ia < nargs && parms == void_list_node)
-    return 1;
+    return unify_too_many_arguments (explain_p, nargs, ia);
   /* Fail if parms are left and they don't have default values.  */
   if (parms && parms != void_list_node
       && TREE_PURPOSE (parms) == NULL_TREE)
-    return 1;
+    {
+      unsigned int count = nargs;
+      tree p = parms;
+      while (p && p != void_list_node)
+       {
+         count++;
+         p = TREE_CHAIN (p);
+       }
+      return unify_too_few_arguments (explain_p, ia, count);
+    }
 
   if (!subr)
     {
@@ -14503,7 +14761,10 @@ type_unification_real (tree tparms,
              tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
              tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
              arg = tsubst_template_arg (arg, targs, tf_none, NULL_TREE);
-             arg = convert_template_argument (parm, arg, targs, tf_none,
+             arg = convert_template_argument (parm, arg, targs,
+                                              (explain_p
+                                               ? tf_warning_or_error
+                                               : tf_none),
                                               i, NULL_TREE);
              if (arg == error_mark_node)
                return 1;
@@ -14540,7 +14801,7 @@ type_unification_real (tree tparms,
              continue;
            }
 
-         return 2;
+         return unify_parameter_deduction_failure (explain_p, tparm);
        }
     }
 #ifdef ENABLE_CHECKING
@@ -14548,7 +14809,7 @@ type_unification_real (tree tparms,
     SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
 #endif
 
-  return 0;
+  return unify_success (explain_p);
 }
 
 /* Subroutine of type_unification_real.  Args are like the variables
@@ -14563,7 +14824,8 @@ resolve_overloaded_unification (tree tparms,
                                tree parm,
                                tree arg,
                                unification_kind_t strict,
-                               int sub_strict)
+                               int sub_strict,
+                               bool explain_p)
 {
   tree tempargs = copy_node (targs);
   int good = 0;
@@ -14615,7 +14877,7 @@ resolve_overloaded_unification (tree tparms,
            {
              elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
              if (try_one_overload (tparms, targs, tempargs, parm,
-                                   elem, strict, sub_strict, addr_p)
+                                   elem, strict, sub_strict, addr_p, explain_p)
                  && (!goodfn || !decls_match (goodfn, elem)))
                {
                  goodfn = elem;
@@ -14643,7 +14905,7 @@ resolve_overloaded_unification (tree tparms,
     for (; arg; arg = OVL_NEXT (arg))
       if (try_one_overload (tparms, targs, tempargs, parm,
                            TREE_TYPE (OVL_CURRENT (arg)),
-                           strict, sub_strict, addr_p)
+                           strict, sub_strict, addr_p, explain_p)
          && (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg))))
        {
          goodfn = OVL_CURRENT (arg);
@@ -14790,7 +15052,8 @@ try_one_overload (tree tparms,
                  tree arg,
                  unification_kind_t strict,
                  int sub_strict,
-                 bool addr_p)
+                 bool addr_p,
+                 bool explain_p)
 {
   int nargs;
   tree tempargs;
@@ -14820,7 +15083,7 @@ try_one_overload (tree tparms,
   nargs = TREE_VEC_LENGTH (targs);
   tempargs = make_tree_vec (nargs);
 
-  if (unify (tparms, tempargs, parm, arg, sub_strict) != 0)
+  if (unify (tparms, tempargs, parm, arg, sub_strict, explain_p))
     return 0;
 
   /* First make sure we didn't deduce anything that conflicts with
@@ -14858,7 +15121,8 @@ try_one_overload (tree tparms,
    TARGS are as for unify.  */
 
 static tree
-try_class_unification (tree tparms, tree targs, tree parm, tree arg)
+try_class_unification (tree tparms, tree targs, tree parm, tree arg,
+                      bool explain_p)
 {
   tree copy_of_targs;
 
@@ -14901,7 +15165,7 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg)
 
   /* If unification failed, we're done.  */
   if (unify (tparms, copy_of_targs, CLASSTYPE_TI_ARGS (parm),
-            CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE))
+            CLASSTYPE_TI_ARGS (arg), UNIFY_ALLOW_NONE, explain_p))
     return NULL_TREE;
 
   return arg;
@@ -14914,8 +15178,9 @@ try_class_unification (tree tparms, tree targs, tree parm, tree arg)
    a partial specialization, as well as a plain template type.  Used
    by unify.  */
 
-static tree
-get_template_base (tree tparms, tree targs, tree parm, tree arg)
+static enum template_base_result
+get_template_base (tree tparms, tree targs, tree parm, tree arg,
+                  bool explain_p, tree *result)
 {
   tree rval = NULL_TREE;
   tree binfo;
@@ -14924,14 +15189,18 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg)
 
   binfo = TYPE_BINFO (complete_type (arg));
   if (!binfo)
-    /* The type could not be completed.  */
-    return NULL_TREE;
+    {
+      /* The type could not be completed.  */
+      *result = NULL_TREE;
+      return tbr_incomplete_type;
+    }
 
   /* Walk in inheritance graph order.  The search order is not
      important, and this avoids multiple walks of virtual bases.  */
   for (binfo = TREE_CHAIN (binfo); binfo; binfo = TREE_CHAIN (binfo))
     {
-      tree r = try_class_unification (tparms, targs, parm, BINFO_TYPE (binfo));
+      tree r = try_class_unification (tparms, targs, parm,
+                                     BINFO_TYPE (binfo), explain_p);
 
       if (r)
        {
@@ -14944,13 +15213,17 @@ get_template_base (tree tparms, tree targs, tree parm, tree arg)
 
             applies.  */
          if (rval && !same_type_p (r, rval))
-           return NULL_TREE;
+           {
+             *result = NULL_TREE;
+             return tbr_ambiguous_baseclass;
+           }
 
          rval = r;
        }
     }
 
-  return rval;
+  *result = rval;
+  return tbr_success;
 }
 
 /* Returns the level of DECL, which declares a template parameter.  */
@@ -15032,6 +15305,12 @@ template_parm_level_and_index (tree parm, int* level, int* index)
     }
 }
 
+#define RECUR_AND_CHECK_FAILURE(TP, TA, P, A, S, EP)                   \
+  do {                                                                 \
+    if (unify (TP, TA, P, A, S, EP))                                   \
+      return 1;                                                                \
+  } while (0);
+
 /* Unifies the remaining arguments in PACKED_ARGS with the pack
    expansion at the end of PACKED_PARMS. Returns 0 if the type
    deduction succeeds, 1 otherwise. STRICT is the same as in
@@ -15039,10 +15318,10 @@ template_parm_level_and_index (tree parm, int* level, int* index)
    call argument list. We'll need to adjust the arguments to make them
    types. SUBR tells us if this is from a recursive call to
    type_unification_real.  */
-int
+static int
 unify_pack_expansion (tree tparms, tree targs, tree packed_parms, 
                       tree packed_args, int strict, bool call_args_p,
-                      bool subr)
+                      bool subr, bool explain_p)
 {
   tree parm 
     = TREE_VEC_ELT (packed_parms, TREE_VEC_LENGTH (packed_parms) - 1);
@@ -15132,7 +15411,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
                     if (resolve_overloaded_unification
                         (tparms, targs, parm, arg,
                         (unification_kind_t) strict,
-                        sub_strict)
+                        sub_strict, explain_p)
                         != 0)
                       return 1;
                     skip_arg_p = true;
@@ -15160,8 +15439,8 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
            /* For deduction from an init-list we need the actual list.  */
            if (arg_expr && BRACE_ENCLOSED_INITIALIZER_P (arg_expr))
              arg = arg_expr;
-            if (unify (tparms, targs, parm, arg, arg_strict))
-              return 1;
+           RECUR_AND_CHECK_FAILURE (tparms, targs, parm, arg, arg_strict,
+                                    explain_p);
           }
       }
 
@@ -15252,13 +15531,21 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
           ARGUMENT_PACK_INCOMPLETE_P (old_pack) = 1;
           ARGUMENT_PACK_EXPLICIT_ARGS (old_pack) = explicit_args;
         }
-      else if (!comp_template_args (ARGUMENT_PACK_ARGS (old_pack),
-                                    new_args))
-        /* Inconsistent unification of this parameter pack.  */
-        return 1;
+      else
+       {
+         tree bad_old_arg, bad_new_arg;
+         tree old_args = ARGUMENT_PACK_ARGS (old_pack);
+
+         if (!comp_template_args_with_info (old_args, new_args,
+                                            &bad_old_arg, &bad_new_arg))
+           /* Inconsistent unification of this parameter pack.  */
+           return unify_parameter_pack_inconsistent (explain_p,
+                                                     bad_old_arg,
+                                                     bad_new_arg);
+       }
     }
 
-  return 0;
+  return unify_success (explain_p);
 }
 
 /* Deduce the value of template parameters.  TPARMS is the (innermost)
@@ -15303,7 +15590,8 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
        qualified at this point.  */
 
 static int
-unify (tree tparms, tree targs, tree parm, tree arg, int strict)
+unify (tree tparms, tree targs, tree parm, tree arg, int strict,
+       bool explain_p)
 {
   int idx;
   tree targ;
@@ -15318,19 +15606,19 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
     parm = TREE_OPERAND (parm, 0);
 
   if (arg == error_mark_node)
-    return 1;
+    return unify_invalid (explain_p);
   if (arg == unknown_type_node
       || arg == init_list_type_node)
     /* We can't deduce anything from this, but we might get all the
        template args from other function args.  */
-    return 0;
+    return unify_success (explain_p);
 
   /* If PARM uses template parameters, then we can't bail out here,
      even if ARG == PARM, since we won't record unifications for the
      template parameters.  We might need them if we're trying to
      figure out which of two things is more specialized.  */
   if (arg == parm && !uses_template_parms (parm))
-    return 0;
+    return unify_success (explain_p);
 
   /* Handle init lists early, so the rest of the function can assume
      we're dealing with a type. */
@@ -15349,7 +15637,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        /* We can only deduce from an initializer list argument if the
           parameter is std::initializer_list; otherwise this is a
           non-deduced context. */
-       return 0;
+       return unify_success (explain_p);
 
       elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
 
@@ -15358,7 +15646,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          int elt_strict = strict;
 
          if (elt == error_mark_node)
-           return 1;
+           return unify_invalid (explain_p);
 
          if (!BRACE_ENCLOSED_INITIALIZER_P (elt))
            {
@@ -15370,8 +15658,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
              elt = type;
            }
 
-         if (unify (tparms, targs, elttype, elt, elt_strict))
-           return 1;
+         RECUR_AND_CHECK_FAILURE (tparms, targs, elttype, elt, elt_strict,
+                                  explain_p);
        }
 
       /* If the std::initializer_list<T> deduction worked, replace the
@@ -15383,7 +15671,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          targ = listify (targ);
          TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = targ;
        }
-      return 0;
+      return unify_success (explain_p);
     }
 
   /* Immediately reject some pairs that won't unify because of
@@ -15400,7 +15688,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
         is more specialized, for example.  */
       && TREE_CODE (arg) != TEMPLATE_TYPE_PARM
       && !check_cv_quals_for_unify (strict_in, arg, parm))
-    return 1;
+    return unify_cv_qual_mismatch (explain_p, parm, arg);
 
   if (!(strict & UNIFY_ALLOW_OUTER_LEVEL)
       && TYPE_P (parm) && !CP_TYPE_CONST_P (parm))
@@ -15418,21 +15706,26 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
       /* In a type which contains a nested-name-specifier, template
         argument values cannot be deduced for template parameters used
         within the nested-name-specifier.  */
-      return 0;
+      return unify_success (explain_p);
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
       if (tparm == error_mark_node)
-       return 1;
+       return unify_invalid (explain_p);
 
       if (TEMPLATE_TYPE_LEVEL (parm)
          != template_decl_level (tparm))
        /* The PARM is not one we're trying to unify.  Just check
           to see if it matches ARG.  */
-       return (TREE_CODE (arg) == TREE_CODE (parm)
-               && same_type_p (parm, arg)) ? 0 : 1;
+       {
+         if (TREE_CODE (arg) == TREE_CODE (parm)
+             && same_type_p (parm, arg))
+           return unify_success (explain_p);
+         else
+           return unify_type_mismatch (explain_p, parm, arg);
+       }
       idx = TEMPLATE_TYPE_IDX (parm);
       targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
@@ -15442,7 +15735,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
           && TREE_CODE (tparm) != TYPE_DECL)
          || (TREE_CODE (parm) == TEMPLATE_TEMPLATE_PARM
              && TREE_CODE (tparm) != TEMPLATE_DECL))
-       return 1;
+       gcc_unreachable ();
 
       if (TREE_CODE (parm) == BOUND_TEMPLATE_TEMPLATE_PARM)
        {
@@ -15450,7 +15743,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
             template parameter.  */
          if (TREE_CODE (arg) != BOUND_TEMPLATE_TEMPLATE_PARM
              && !CLASSTYPE_SPECIALIZATION_OF_PRIMARY_TEMPLATE_P (arg))
-           return 1;
+           return unify_template_deduction_failure (explain_p, parm, arg);
 
          {
            tree parmvec = TYPE_TI_ARGS (parm);
@@ -15492,7 +15785,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
            if (coerce_template_parms (parm_parms,
                                        full_argvec,
                                       TYPE_TI_TEMPLATE (parm),
-                                      tf_none,
+                                      (explain_p
+                                       ? tf_warning_or_error
+                                       : tf_none),
                                       /*require_all_args=*/true,
                                       /*use_default_args=*/false)
                == error_mark_node)
@@ -15515,15 +15810,15 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
               parm_variadic_p = 1;
             
             if (TREE_VEC_LENGTH (argvec) < len - parm_variadic_p)
-              return 1;
+              return unify_too_few_arguments (explain_p,
+                                             TREE_VEC_LENGTH (argvec), len);
 
              for (i = 0; i < len - parm_variadic_p; ++i)
              {
-               if (unify (tparms, targs,
-                          TREE_VEC_ELT (parmvec, i),
-                          TREE_VEC_ELT (argvec, i),
-                          UNIFY_ALLOW_NONE))
-                 return 1;
+               RECUR_AND_CHECK_FAILURE (tparms, targs,
+                                        TREE_VEC_ELT (parmvec, i),
+                                        TREE_VEC_ELT (argvec, i),
+                                        UNIFY_ALLOW_NONE, explain_p);
              }
 
            if (parm_variadic_p
@@ -15531,7 +15826,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                                         parmvec, argvec,
                                         UNIFY_ALLOW_NONE,
                                         /*call_args_p=*/false,
-                                        /*subr=*/false))
+                                        /*subr=*/false, explain_p))
              return 1;
          }
          arg = TYPE_TI_TEMPLATE (arg);
@@ -15546,9 +15841,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
          /* Simple cases: Value already set, does match or doesn't.  */
          if (targ != NULL_TREE && template_args_equal (targ, arg))
-           return 0;
+           return unify_success (explain_p);
          else if (targ)
-           return 1;
+           return unify_inconsistency (explain_p, parm, targ, arg);
        }
       else
        {
@@ -15558,20 +15853,20 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
             that binds `const int' to `T'.  */
          if (!check_cv_quals_for_unify (strict_in | UNIFY_ALLOW_LESS_CV_QUAL,
                                         arg, parm))
-           return 1;
+           return unify_cv_qual_mismatch (explain_p, parm, arg);
 
          /* Consider the case where ARG is `const volatile int' and
             PARM is `const T'.  Then, T should be `volatile int'.  */
          arg = cp_build_qualified_type_real
            (arg, cp_type_quals (arg) & ~cp_type_quals (parm), tf_none);
          if (arg == error_mark_node)
-           return 1;
+           return unify_invalid (explain_p);
 
          /* Simple cases: Value already set, does match or doesn't.  */
          if (targ != NULL_TREE && same_type_p (targ, arg))
-           return 0;
+           return unify_success (explain_p);
          else if (targ)
-           return 1;
+           return unify_inconsistency (explain_p, parm, targ, arg);
 
          /* Make sure that ARG is not a variable-sized array.  (Note
             that were talking about variable-sized arrays (like
@@ -15581,7 +15876,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
             instantiation.  Besides, such types are not allowed in
             ISO C++, so we can do as we please here.  */
          if (variably_modified_type_p (arg, NULL_TREE))
-           return 1;
+           return unify_vla_arg (explain_p, arg);
 
          /* Strip typedefs as in convert_template_argument.  */
          arg = canonicalize_type_argument (arg, tf_none);
@@ -15591,35 +15886,45 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
         against it unless PARM is also a parameter pack.  */
       if ((template_parameter_pack_p (arg) || PACK_EXPANSION_P (arg))
          && !template_parameter_pack_p (parm))
-       return 1;
+       return unify_parameter_pack_mismatch (explain_p, parm, arg);
 
       /* If the argument deduction results is a METHOD_TYPE,
          then there is a problem.
          METHOD_TYPE doesn't map to any real C++ type the result of
         the deduction can not be of that type.  */
       if (TREE_CODE (arg) == METHOD_TYPE)
-       return 1;
+       return unify_method_type_error (explain_p, arg);
 
       TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
-      return 0;
+      return unify_success (explain_p);
 
     case TEMPLATE_PARM_INDEX:
       tparm = TREE_VALUE (TREE_VEC_ELT (tparms, 0));
       if (tparm == error_mark_node)
-       return 1;
+       return unify_invalid (explain_p);
 
       if (TEMPLATE_PARM_LEVEL (parm)
          != template_decl_level (tparm))
-       /* The PARM is not one we're trying to unify.  Just check
-          to see if it matches ARG.  */
-       return !(TREE_CODE (arg) == TREE_CODE (parm)
-                && cp_tree_equal (parm, arg));
+       {
+         /* The PARM is not one we're trying to unify.  Just check
+            to see if it matches ARG.  */
+         int result = !(TREE_CODE (arg) == TREE_CODE (parm)
+                        && cp_tree_equal (parm, arg));
+         if (result)
+           unify_expression_unequal (explain_p, parm, arg);
+         return result;
+       }
 
       idx = TEMPLATE_PARM_IDX (parm);
       targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
 
       if (targ)
-       return !cp_tree_equal (targ, arg);
+       {
+         int x = !cp_tree_equal (targ, arg);
+         if (x)
+           unify_inconsistency (explain_p, parm, targ, arg);
+         return x;
+       }
 
       /* [temp.deduct.type] If, in the declaration of a function template
         with a non-type template-parameter, the non-type
@@ -15646,25 +15951,25 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
       else if (uses_template_parms (tparm))
        /* We haven't deduced the type of this parameter yet.  Try again
           later.  */
-       return 0;
+       return unify_success (explain_p);
       else
-       return 1;
+       return unify_type_mismatch (explain_p, tparm, arg);
 
       /* If ARG is a parameter pack or an expansion, we cannot unify
         against it unless PARM is also a parameter pack.  */
       if ((template_parameter_pack_p (arg) || PACK_EXPANSION_P (arg))
          && !TEMPLATE_PARM_PARAMETER_PACK (parm))
-       return 1;
+       return unify_parameter_pack_mismatch (explain_p, parm, arg);
 
       TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
-      return 0;
+      return unify_success (explain_p);
 
     case PTRMEM_CST:
      {
        /* A pointer-to-member constant can be unified only with
         another constant.  */
       if (TREE_CODE (arg) != PTRMEM_CST)
-       return 1;
+       return unify_ptrmem_cst_mismatch (explain_p, parm, arg);
 
       /* Just unify the class member. It would be useless (and possibly
         wrong, depending on the strict flags) to unify also
@@ -15677,13 +15982,13 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
         Unification of &A::x and &B::x must succeed.  */
       return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
-                   PTRMEM_CST_MEMBER (arg), strict);
+                   PTRMEM_CST_MEMBER (arg), strict, explain_p);
      }
 
     case POINTER_TYPE:
       {
        if (TREE_CODE (arg) != POINTER_TYPE)
-         return 1;
+         return unify_type_mismatch (explain_p, parm, arg);
 
        /* [temp.deduct.call]
 
@@ -15701,21 +16006,21 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
          strict |= (strict_in & UNIFY_ALLOW_DERIVED);
 
        return unify (tparms, targs, TREE_TYPE (parm),
-                     TREE_TYPE (arg), strict);
+                     TREE_TYPE (arg), strict, explain_p);
       }
 
     case REFERENCE_TYPE:
       if (TREE_CODE (arg) != REFERENCE_TYPE)
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
-                   strict & UNIFY_ALLOW_MORE_CV_QUAL);
+                   strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
 
     case ARRAY_TYPE:
       if (TREE_CODE (arg) != ARRAY_TYPE)
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
       if ((TYPE_DOMAIN (parm) == NULL_TREE)
          != (TYPE_DOMAIN (arg) == NULL_TREE))
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
       if (TYPE_DOMAIN (parm) != NULL_TREE)
        {
          tree parm_max;
@@ -15754,7 +16059,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                 Here, the type of the ARG will be "int [g(i)]", and
                 may be a SAVE_EXPR, etc.  */
              if (TREE_CODE (arg_max) != MINUS_EXPR)
-               return 1;
+               return unify_vla_arg (explain_p, arg);
              arg_max = TREE_OPERAND (arg_max, 0);
            }
 
@@ -15771,11 +16076,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                                   arg_max,
                                   integer_one_node);
 
-         if (unify (tparms, targs, parm_max, arg_max, UNIFY_ALLOW_INTEGER))
-           return 1;
+         RECUR_AND_CHECK_FAILURE (tparms, targs, parm_max, arg_max,
+                                  UNIFY_ALLOW_INTEGER, explain_p);
        }
       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
-                   strict & UNIFY_ALLOW_MORE_CV_QUAL);
+                   strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
 
     case REAL_TYPE:
     case COMPLEX_TYPE:
@@ -15785,16 +16090,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
     case ENUMERAL_TYPE:
     case VOID_TYPE:
       if (TREE_CODE (arg) != TREE_CODE (parm))
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
 
       /* We have already checked cv-qualification at the top of the
         function.  */
       if (!same_type_ignoring_top_level_qualifiers_p (arg, parm))
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
 
       /* As far as unification is concerned, this wins.         Later checks
         will invalidate it if necessary.  */
-      return 0;
+      return unify_success (explain_p);
 
       /* Types INTEGER_CST and MINUS_EXPR can come from array bounds.  */
       /* Type INTEGER_CST can come from ordinary constant template args.  */
@@ -15803,38 +16108,41 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        arg = TREE_OPERAND (arg, 0);
 
       if (TREE_CODE (arg) != INTEGER_CST)
-       return 1;
-      return !tree_int_cst_equal (parm, arg);
+       return unify_template_argument_mismatch (explain_p, parm, arg);
+      return (tree_int_cst_equal (parm, arg)
+             ? unify_success (explain_p)
+             : unify_template_argument_mismatch (explain_p, parm, arg));
 
     case TREE_VEC:
       {
        int i;
        if (TREE_CODE (arg) != TREE_VEC)
-         return 1;
+         return unify_template_argument_mismatch (explain_p, parm, arg);
        if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg))
-         return 1;
+         return unify_arity (explain_p, TREE_VEC_LENGTH (arg),
+                             TREE_VEC_LENGTH (parm));
        for (i = 0; i < TREE_VEC_LENGTH (parm); ++i)
-         if (unify (tparms, targs,
-                    TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
-                    UNIFY_ALLOW_NONE))
-           return 1;
-       return 0;
+         RECUR_AND_CHECK_FAILURE (tparms, targs,
+                                  TREE_VEC_ELT (parm, i),
+                                  TREE_VEC_ELT (arg, i),
+                                  UNIFY_ALLOW_NONE, explain_p);
+       return unify_success (explain_p);
       }
 
     case RECORD_TYPE:
     case UNION_TYPE:
       if (TREE_CODE (arg) != TREE_CODE (parm))
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
 
       if (TYPE_PTRMEMFUNC_P (parm))
        {
          if (!TYPE_PTRMEMFUNC_P (arg))
-           return 1;
+           return unify_type_mismatch (explain_p, parm, arg);
 
          return unify (tparms, targs,
                        TYPE_PTRMEMFUNC_FN_TYPE (parm),
                        TYPE_PTRMEMFUNC_FN_TYPE (arg),
-                       strict);
+                       strict, explain_p);
        }
 
       if (CLASSTYPE_TEMPLATE_INFO (parm))
@@ -15845,7 +16153,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
            {
              /* First, we try to unify the PARM and ARG directly.  */
              t = try_class_unification (tparms, targs,
-                                        parm, arg);
+                                        parm, arg, explain_p);
 
              if (!t)
                {
@@ -15858,10 +16166,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                       a class of the form template-id, A can be a
                       pointer to a derived class pointed to by the
                       deduced A.  */
-                 t = get_template_base (tparms, targs, parm, arg);
+                 enum template_base_result r;
+                 r = get_template_base (tparms, targs, parm, arg,
+                                        explain_p, &t);
 
                  if (!t)
-                   return 1;
+                   return unify_no_common_base (explain_p, r, parm, arg);
                }
            }
          else if (CLASSTYPE_TEMPLATE_INFO (arg)
@@ -15872,14 +16182,14 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
            t = arg;
          else
            /* There's no chance of unification succeeding.  */
-           return 1;
+           return unify_type_mismatch (explain_p, parm, arg);
 
          return unify (tparms, targs, CLASSTYPE_TI_ARGS (parm),
-                       CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE);
+                       CLASSTYPE_TI_ARGS (t), UNIFY_ALLOW_NONE, explain_p);
        }
       else if (!same_type_ignoring_top_level_qualifiers_p (parm, arg))
-       return 1;
-      return 0;
+       return unify_type_mismatch (explain_p, parm, arg);
+      return unify_success (explain_p);
 
     case METHOD_TYPE:
     case FUNCTION_TYPE:
@@ -15890,7 +16200,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
        unsigned int i;
 
        if (TREE_CODE (arg) != TREE_CODE (parm))
-         return 1;
+         return unify_type_mismatch (explain_p, parm, arg);
 
        /* CV qualifications for methods can never be deduced, they must
           match exactly.  We need to check them explicitly here,
@@ -15901,11 +16211,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                (UNIFY_ALLOW_NONE,
                 class_of_this_parm (arg),
                 class_of_this_parm (parm))))
-         return 1;
+         return unify_cv_qual_mismatch (explain_p, parm, arg);
 
-       if (unify (tparms, targs, TREE_TYPE (parm),
-                  TREE_TYPE (arg), UNIFY_ALLOW_NONE))
-         return 1;
+       RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm),
+                                TREE_TYPE (arg), UNIFY_ALLOW_NONE, explain_p);
 
        nargs = list_length (TYPE_ARG_TYPES (arg));
        args = XALLOCAVEC (tree, nargs);
@@ -15917,7 +16226,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
        return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
                                      args, nargs, 1, DEDUCE_EXACT,
-                                     LOOKUP_NORMAL);
+                                     LOOKUP_NORMAL, explain_p);
       }
 
     case OFFSET_TYPE:
@@ -15930,11 +16239,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
          /* Check top-level cv qualifiers */
          if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
-           return 1;
+           return unify_cv_qual_mismatch (explain_p, parm, arg);
 
-         if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
-                    TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
-           return 1;
+         RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+                                  TYPE_PTRMEMFUNC_OBJECT_TYPE (arg),
+                                  UNIFY_ALLOW_NONE, explain_p);
 
          /* Determine the type of the function we are unifying against. */
          method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
@@ -15946,28 +16255,28 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
             implicit object parameter and place them on the function
             type to be restored later. */
          fntype = apply_memfn_quals (fntype, type_memfn_quals (method_type));
-         return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
+         return unify (tparms, targs, TREE_TYPE (parm), fntype, strict, explain_p);
        }
 
       if (TREE_CODE (arg) != OFFSET_TYPE)
-       return 1;
-      if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
-                TYPE_OFFSET_BASETYPE (arg), UNIFY_ALLOW_NONE))
-       return 1;
+       return unify_type_mismatch (explain_p, parm, arg);
+      RECUR_AND_CHECK_FAILURE (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+                              TYPE_OFFSET_BASETYPE (arg),
+                              UNIFY_ALLOW_NONE, explain_p);
       return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
-                   strict);
+                   strict, explain_p);
 
     case CONST_DECL:
       if (DECL_TEMPLATE_PARM_P (parm))
-       return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
+       return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, explain_p);
       if (arg != integral_constant_value (parm))
-       return 1;
-      return 0;
+       return unify_template_argument_mismatch (explain_p, parm, arg);
+      return unify_success (explain_p);
 
     case FIELD_DECL:
     case TEMPLATE_DECL:
       /* Matched cases are handled by the ARG == PARM test above.  */
-      return 1;
+      return unify_template_argument_mismatch (explain_p, parm, arg);
 
     case VAR_DECL:
       /* A non-type template parameter that is a variable should be a
@@ -15997,7 +16306,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
                  /* Since there is something following the pack
                     expansion, we cannot unify this template argument
                     list.  */
-                 return 0;
+                 return unify_success (explain_p);
              }
          }
          
@@ -16006,25 +16315,27 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
            (not counting the pack expression at the end), or we have
            too many arguments for a parameter list that doesn't end in
            a pack expression, we can't unify.  */
-        if (argslen < (len - parm_variadic_p)
-            || (argslen > len && !parm_variadic_p))
-          return 1;
+        if (argslen < (len - parm_variadic_p))
+         return unify_too_few_arguments (explain_p, argslen, len);
+       if (argslen > len && !parm_variadic_p)
+         return unify_too_many_arguments (explain_p, argslen, len);
 
         /* Unify all of the parameters that precede the (optional)
            pack expression.  */
         for (i = 0; i < len - parm_variadic_p; ++i)
           {
-            if (unify (tparms, targs, TREE_VEC_ELT (packed_parms, i),
-                       TREE_VEC_ELT (packed_args, i), strict))
-              return 1;
+           RECUR_AND_CHECK_FAILURE (tparms, targs,
+                                    TREE_VEC_ELT (packed_parms, i),
+                                    TREE_VEC_ELT (packed_args, i),
+                                    strict, explain_p);
           }
 
         if (parm_variadic_p)
           return unify_pack_expansion (tparms, targs, 
                                        packed_parms, packed_args,
                                        strict, /*call_args_p=*/false,
-                                       /*subr=*/false);
-        return 0;
+                                       /*subr=*/false, explain_p);
+        return unify_success (explain_p);
       }
 
       break;
@@ -16034,16 +16345,16 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
     case UNDERLYING_TYPE:
       /* Cannot deduce anything from TYPEOF_TYPE, DECLTYPE_TYPE,
         or UNDERLYING_TYPE nodes.  */
-      return 0;
+      return unify_success (explain_p);
 
     case ERROR_MARK:
       /* Unification fails if we hit an error node.  */
-      return 1;
+      return unify_invalid (explain_p);
 
     default:
       /* An unresolved overload is a nondeduced context.  */
       if (type_unknown_p (parm))
-       return 0;
+       return unify_success (explain_p);
       gcc_assert (EXPR_P (parm));
 
       /* We must be looking at an expression.  This can happen with
@@ -16067,11 +16378,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 
       if (!uses_template_parms (parm)
          && !template_args_equal (parm, arg))
-       return 1;
+       return unify_expression_unequal (explain_p, parm, arg);
       else
-       return 0;
+       return unify_success (explain_p);
     }
 }
+#undef RECUR_AND_CHECK_FAILURE
 \f
 /* Note that DECL can be defined in this translation unit, if
    required.  */
@@ -16334,10 +16646,11 @@ more_specialized_fn (tree pat1, tree pat2, int len)
           for (i = 0; i < len2; i++, ta = TREE_CHAIN (ta))
             TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
 
-          deduce1 = !unify_pack_expansion (tparms1, targs1, parmvec, 
+          deduce1 = (unify_pack_expansion (tparms1, targs1, parmvec,
                                           argvec, UNIFY_ALLOW_NONE, 
                                            /*call_args_p=*/false, 
-                                          /*subr=*/0);
+                                          /*subr=*/0, /*explain_p=*/false)
+                    == 0);
 
           /* We cannot deduce in the other direction, because ARG1 is
              a pack expansion but ARG2 is not.  */
@@ -16358,10 +16671,11 @@ more_specialized_fn (tree pat1, tree pat2, int len)
           for (i = 0; i < len1; i++, ta = TREE_CHAIN (ta))
             TREE_VEC_ELT (argvec, i) = TREE_VALUE (ta);
 
-          deduce2 = !unify_pack_expansion (tparms2, targs2, parmvec, 
+          deduce2 = (unify_pack_expansion (tparms2, targs2, parmvec,
                                           argvec, UNIFY_ALLOW_NONE, 
                                            /*call_args_p=*/false, 
-                                          /*subr=*/0);
+                                          /*subr=*/0, /*explain_p=*/false)
+                    == 0);
 
           /* We cannot deduce in the other direction, because ARG2 is
              a pack expansion but ARG1 is not.*/
@@ -16372,8 +16686,12 @@ more_specialized_fn (tree pat1, tree pat2, int len)
         {
           /* The normal case, where neither argument is a pack
              expansion.  */
-          deduce1 = !unify (tparms1, targs1, arg1, arg2, UNIFY_ALLOW_NONE);
-          deduce2 = !unify (tparms2, targs2, arg2, arg1, UNIFY_ALLOW_NONE);
+          deduce1 = (unify (tparms1, targs1, arg1, arg2,
+                           UNIFY_ALLOW_NONE, /*explain_p=*/false)
+                    == 0);
+          deduce2 = (unify (tparms2, targs2, arg2, arg1,
+                           UNIFY_ALLOW_NONE, /*explain_p=*/false)
+                    == 0);
         }
 
       /* If we couldn't deduce arguments for tparms1 to make arg1 match
@@ -16587,7 +16905,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
                           args, ix,
                           (check_rettype || DECL_CONV_FN_P (fn)
                            ? TREE_TYPE (decl_type) : NULL_TREE),
-                          DEDUCE_EXACT, LOOKUP_NORMAL))
+                          DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false))
     return NULL_TREE;
 
   return targs;
@@ -16629,7 +16947,7 @@ get_class_bindings (tree tparms, tree spec_args, tree args)
   if (unify (tparms, deduced_args,
             INNERMOST_TEMPLATE_ARGS (spec_args),
             INNERMOST_TEMPLATE_ARGS (args),
-            UNIFY_ALLOW_NONE))
+            UNIFY_ALLOW_NONE, /*explain_p=*/false))
     return NULL_TREE;
 
   for (i =  0; i < ntparms; ++i)
@@ -19436,7 +19754,8 @@ do_auto_deduction (tree type, tree init, tree auto_node)
   TREE_VEC_ELT (tparms, 0)
     = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
   val = type_unification_real (tparms, targs, parms, args, 1, 0,
-                              DEDUCE_CALL, LOOKUP_NORMAL);
+                              DEDUCE_CALL, LOOKUP_NORMAL,
+                              /*explain_p=*/false);
   if (val > 0)
     {
       if (processing_template_decl)
index 258128b513cf65459164ebde419491376a09ee5e..1c00214e92974829b7056a5548027f39ba41d7d5 100644 (file)
@@ -1,3 +1,61 @@
+2011-07-16  Nathan Froyd  <froydnj@codesourcery.com>
+           Jason Merrill  <jason@redhat.com>
+
+       PR c++/45329
+       PR c++/48934
+       * g++.dg/cpp0x/decltype29.C: Adjust.
+       * g++.dg/cpp0x/error4.C: Adjust.
+       * g++.dg/cpp0x/sfinae26.C: Adjust.
+       * g++.dg/cpp0x/variadic105.C: Adjust.
+       * g++.dg/template/deduce3.C: Adjust.
+       * g++.dg/template/error45.C: Adjust.
+       * g++.dg/template/ptrmem2.C: Adjust.
+       * g++.dg/template/sfinae2.C: Adjust.
+       * g++.old-deja/g++.pt/crash60.C: Adjust.
+       * g++.old-deja/g++.pt/unify6.C: Adjust.
+       * g++.dg/cpp0x/lambda/lambda-ice2.C: Adjust.
+       * g++.dg/cpp0x/nullptr15.C: Adjust.
+       * g++.dg/cpp0x/pr31431-2.C: Adjust.
+       * g++.dg/cpp0x/pr31431.C: Adjust.
+       * g++.dg/cpp0x/pr31434.C: Adjust.
+       * g++.dg/cpp0x/sfinae11.C: Adjust
+       * g++.dg/cpp0x/temp_default2.C: Adjust.
+       * g++.dg/cpp0x/trailing4.C: Adjust.
+       * g++.dg/cpp0x/variadic-ex3.C: Adjust.
+       * g++.dg/cpp0x/variadic-ex4.C: Adjust.
+       * g++.dg/cpp0x/variadic105.C: Adjust.
+       * g++.dg/cpp0x/vt-37737-2.C: Adjust.
+       * g++.dg/ext/vla2.C: Adjust.
+       * g++.dg/other/ptrmem10.C: Adjust.
+       * g++.dg/other/ptrmem11.C: Adjust.
+       * g++.dg/overload/unknown1.C: Adjust.
+       * g++.dg/template/conv11.C: Adjust.
+       * g++.dg/template/dependent-expr5.C: Adjust.
+       * g++.dg/template/friend.C: Adjust.
+       * g++.dg/template/incomplete2.C: Adjust.
+       * g++.dg/template/local4.C: Adjust.
+       * g++.dg/template/local6.C: Adjust.
+       * g++.dg/template/operator9.C: Adjust.
+       * g++.dg/template/ttp25.C: Adjust.
+       * g++.dg/template/unify10.C: Adjust.
+       * g++.dg/template/unify11.C: Adjust.
+       * g++.dg/template/unify6.C: Adjust.
+       * g++.dg/template/unify9.C: Adjust.
+       * g++.dg/template/varmod1.C: Adjust.
+       * g++.old-deja/g++.brendan/crash56.C: Adjust.
+       * g++.old-deja/g++.pt/crash28.C: Adjust.
+       * g++.old-deja/g++.pt/explicit41.C: Adjust.
+       * g++.old-deja/g++.pt/explicit77.C: Adjust.
+       * g++.old-deja/g++.pt/expr2.C: Adjust.
+       * g++.old-deja/g++.pt/ptrmem6.C: Adjust.
+       * g++.old-deja/g++.pt/spec5.C: Adjust.
+       * g++.old-deja/g++.pt/spec6.C: Adjust.
+       * g++.old-deja/g++.pt/unify4.C: Adjust.
+       * g++.old-deja/g++.pt/unify8.C: Adjust.
+       * g++.old-deja/g++.robertl/eb98.C: Adjust.
+       * g++.dg/overload/template5.C: New testcase.
+       * g++.dg/template/overload12.C: New testcase.
+
 2011-07-11  Tobias Burnus  <burnus@net-b.de>
 
        * gfortran.dg/coarray_14.f90: Remove dg-error "sorry not implemented".
index 2bb79d07e78aa855790163d2ad727b2a44a000e2..70fe4412dcb00c25705ede35d1f9555a8b3cd3c5 100644 (file)
@@ -13,7 +13,7 @@ decltype (ft<F> (F()))
 ft() {}                                // { dg-error "depth" }
 
 int main() {
-    ft<struct a*, 0>();                // { dg-error "no match" }
+    ft<struct a*, 0>();                // { dg-error "no match|wrong number" }
 }
 
 // { dg-prune-output "note" }
index 29a1cddab16f553ccda9e10d3ce16a4fde2e8c65..064c2f2f6204c14a9c576e26ebaad3cb170f4d87 100644 (file)
@@ -10,7 +10,7 @@ struct S {
     static U get(const volatile T&);
 
   template<typename U>
-    static decltype(*declval<U>()) get(...);
+    static decltype(*declval<U>()) get(...); // { dg-error "operator*" }
 
   typedef decltype(get<T>(declval<T>())) type; // { dg-error "no match" }
 };
index 352137aad241907bbe4575ba78c1f8b421856919..8d7d093dc409b7c67434a64f1961002b9b8ea2c4 100644 (file)
@@ -9,8 +9,9 @@ decltype(F()) run(F f) // { dg-message "note" }
 
 int main()
 {
-  auto l = []() { return 5; };
+  auto l = []() { return 5; }; // { dg-error "lambda closure type" }
 
   run(l); // { dg-error "no match" }
   // { dg-message "candidate" "candidate note" { target *-*-* } 14 }
+  // { dg-error "use of deleted function" "candidate explanation" { target *-*-* } 5 }
 }
index e02fd5592eb9a1ab60c2c50dec8a2999e0c87771..af661ecc3af5023e1ae3be4c7d0eeb8b87bb9c43 100644 (file)
@@ -17,10 +17,10 @@ void test_g()
   // Deduction to nullptr_t, no deduction to pointer type
   //
   g(nullptr);               // { dg-error "no matching function for call to " }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 19 }
+  // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 19 }
   type_equal<float*>(g((float*)nullptr));
   decltype(nullptr) mynull = 0;
   g(mynull);                // { dg-error "no matching function for call to " }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 23 }
+  // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 23 }
   type_equal<float*>(g((float*)mynull));
 }
index 15efbc5d35973312082f4f2b279f910f9a25e437..076493938a8e6a9d8d57cab34a3f562ce3ee570a 100644 (file)
@@ -4,5 +4,5 @@ template<typename, typename..., typename> void foo(); // { dg-message "note" }
 void bar()
 {
   foo<int>(); // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 6 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 }
 }
index 36f341f3d02ed4121822aacc07e714eaba60f515..afd323715746d3e120a344a839565426fbf329c2 100644 (file)
@@ -4,5 +4,5 @@ template<typename..., typename> void foo(); // { dg-message "note" }
 void bar()
 {
   foo<int>(); // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 6 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 }
 }
index 97ad079ab0b8b022d3429d2a0ff195a725a9c2a6..54786167c35bef5c2fb163b194a72d68c739893e 100644 (file)
@@ -8,5 +8,5 @@ template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" }
 void bar()
 {
   foo(0); // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+  // { dg-message "(candidate|cannot convert)" "candidate note" { target *-*-* } 10 }
 }
index 117b08bb623dec3bc150449f5c3006648e6e2782..e62c08984e78ee193a18bccc3a3cf08faa141a1b 100644 (file)
@@ -51,6 +51,6 @@ int main()
   // static_assert(  noexcept( f3(y) ), "shall be ill-formed(OK)." );
 
   noexcept( f1(z) );           // { dg-message "required" }
-  static_assert(  noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match" }
+  static_assert(  noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match|could not convert" }
   noexcept( f3(z) );           // { dg-message "required" }
 }
index 5b8cdd9f5457d5885132b524a9b79cc16c38081e..42b48eb5a6b27a49a61e102a68fe84098d17d671 100644 (file)
@@ -32,7 +32,7 @@ struct S {
   template<class... U,
     typename enable_if<and_<is_same<T, U>...>::value>::type*& = enabler
   >
-  S(U...){} // #
+  S(U...){}                    // { dg-error "no type named 'type'" }
 };
 
 S<bool> s(0);                  // { dg-error "no match" }
index fa2bb6aed863b526e00d3872fb4664289abce75f..dab1650e448018a8d7d28aecf9dea946ae344306 100644 (file)
@@ -8,7 +8,7 @@ void g()
   f(1, 'c'); // f<int,char>(1,'c') 
   f(1); // f<int,double>(1,0) 
   f(); // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 }
   f<int>(); // f<int,double>(0,0) 
   f<int,char>(); // f<int,char>(0,0) 
 } 
index d67b3b61151622f562239cbff1d3b98b08273232..8d4baa97e5d5172c0f6d3e00bdcb1f1c985e771e 100644 (file)
@@ -8,5 +8,5 @@ auto f(T,U) -> decltype(T() + U())
 template<class T> void g(T){}  // { dg-message "note" }
 
 int main() { g(f); }           // { dg-error "no matching function" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+// { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 }
 
index bd973055d062a452b4aae0fe74ea9e9980577021..018eaa3ed8b85b6a98b56ed45824af7d788ec02d 100644 (file)
@@ -4,8 +4,8 @@ void g()
 { 
   int i = f<int>(5.6);
   int j = f(5.6);         // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 6 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 }
   f<void>(f<int, bool>);
   f<void>(f<int>);        // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 9 }
 } 
index 5bf211696a3170d71bfbdc4c0e97eb3c7891a5c8..0a777c4853bf7d37807d334556bf390a1d97620a 100644 (file)
@@ -8,6 +8,6 @@ void g()
   f<int>("aa",3.0); // Y is deduced to be char*, and 
                     // Z is deduced to be double 
   f("aa",3.0); // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 }
   f2<char, short, int, long>(); // okay
 } 
index 24d7e15be2f2d349f5ac11ad9679a2cb25fd4f2e..66387b23c473fc9441d7748e1d8e09ad21b5cb8f 100644 (file)
@@ -21,4 +21,5 @@ struct call_sum {
 int main() {
   // This shouldn't be an error; this is bug 35722.
   reverse<call_sum>(1,2);      // { dg-bogus "no match" "" { xfail *-*-* } }
+  // { dg-bogus "sorry, unimplemented" "candidate explanation" { xfail *-*-* } 6 }
 }
index 2ff7e5b0b51db5c5342f21e2305c03eb3579bb4e..5514259ec3f46bb0805649522c98f0528400d8be 100644 (file)
@@ -4,7 +4,7 @@ template<class U, class... T>
 void f()                       // { dg-message "note" }
 {
   f<T...>(); // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 6 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 6 }
 }
 
 template<>
index f6a9debca98731446de86efea51081bb034e1955..3e83c8b3de969180b627cb5d413df668c8f396b6 100644 (file)
@@ -15,5 +15,5 @@ void bar(int i)
   char d[i] ;
   
   begin(d);  // { dg-error "no matching function" "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
+  // { dg-message "(candidate|valid template argument)" "candidate note" { target *-*-* } 17 }
 }
index bc386ed56befa123414430bfbdac22188465b6b1..a17df7fb362552a96ca1b32d775fc1a60d2030fd 100644 (file)
@@ -13,7 +13,7 @@ template <class C>
 static void
 bar(C *c, void (C::*m) ())
 {
-  foo<C,m>((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun)" }
+  foo<C,m>((void *)c);// { dg-error "(not a valid template arg|pointer-to-member|no matching fun|could not convert)" }
   // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
 }
 
index 119cbb078a2f97f42d4ffc4f2968021a45d3158f..e73164eef26bc28899b40236303cabe922c65b6e 100644 (file)
@@ -14,7 +14,7 @@ template <typename T>
 int
 bar(int T::* p)
 {
-  return foo<p>(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member)" }
+  return foo<p>(0);// { dg-error "(not a valid template arg|no matching func|pointer-to-member|could not convert)" }
   // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
 }
 
diff --git a/gcc/testsuite/g++.dg/overload/template5.C b/gcc/testsuite/g++.dg/overload/template5.C
new file mode 100644 (file)
index 0000000..b1dc65e
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile }
+
+template<typename T>
+int low(T a, T b, T c) { return a + b + c; } // { dg-message "template" }
+
+template<typename T>
+int high(T a, T b, T c) { return a + b + c; } // { dg-message "template" }
+
+int test (void)
+{
+  low (5, 6);                  // { dg-error "no matching function" }
+  // { dg-message "(candidate|3 arguments, 2 provided)" "" { target *-*-* } 11 }
+  high (5, 6, 7, 8);           // { dg-error "no matching function" }
+  // { dg-message "(candidate|3 arguments, 4 provided)" "" { target *-*-* } 13 }
+}
index 935f8d4963da77ba67c8a844a1f77b8def2a4325..128c4344fede4e2f0427884dba9165d0825f8a72 100644 (file)
@@ -6,5 +6,5 @@ template <typename T> void bar(T f); // { dg-message "note" }
 
 void baz() {
   bar(foo); // { dg-error "<unresolved overloaded function type>" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 8 }
 }
index 57d06af3ee75ed89115a1d5e567b06ed83f116e9..f08e756a3ee0bdea4858f9ba14ee93424c538a86 100644 (file)
@@ -7,5 +7,5 @@ struct A
 int main()
 {
   A().operator int();          // { dg-error "operator int" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
+  // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 9 }
 }
index e8a1d4e2b51cea72d23548a453f62baf69c6f5c8..c5d6e00daf70cf24c8516e302ea3577179ea98b7 100644 (file)
@@ -4,8 +4,8 @@ void f(int, T (*)() = 0);       // { dg-message "note" }
 void g() {
   typedef int A[2];
   f<A>(0); // { dg-error "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 6 }
+  // { dg-error "returning an array" "candidate explanation" { target *-*-* } 2 }
   typedef void F();
   f<F>(0); // { dg-error "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
+  // { dg-error "returning a function" "candidate explanation" { target *-*-* } 2 }
 }
index 1e850cd54e5f0d4f97a30a3b94346a2de3927487..af0dfb912a22e298a2020632bc058500c27e6813 100644 (file)
@@ -40,12 +40,12 @@ struct foo {
       bind (&bar::baikt);
 
       bind (&barf); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 42 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 42 }
       bind (&foo::barf); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 44 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 44 }
 
       bindm (&barf); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 47 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 47 }
       bindm (&foo::barf);
 
       bindn (&barf);
@@ -53,15 +53,15 @@ struct foo {
 
       bindb (&barf);
       bindb (&foo::barf); // { dg-error "ambiguous" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 55 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 55 }
 
       bind (&bark); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 58 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 58 }
       bind (&bar::bark); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 60 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 60 }
 
       bindm (&bark); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 63 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 63 }
       bindm (&bar::bark);
 
       bindn (&bark);
@@ -69,7 +69,7 @@ struct foo {
 
       bindb (&bark);
       bindb (&bar::bark); // { dg-error "ambiguous" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 71 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 71 }
     }
   };
 
@@ -92,12 +92,12 @@ struct foo {
       bind (&barT::baikt);
 
       bind (&barf); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 94 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 94 }
       bind (&foo::barf); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 96 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 96 }
 
       bindm (&barf); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 99 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 99 }
       bindm (&foo::barf);
 
       bindn (&barf);
@@ -105,15 +105,15 @@ struct foo {
 
       bindb (&barf);
       bindb (&foo::barf); // { dg-error "ambiguous" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 107 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 107 }
 
       bind (&bark); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 110 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 110 }
       bind (&barT::bark); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 112 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 112 }
 
       bindm (&bark); // { dg-error "no matching function" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 115 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 115 }
       bindm (&barT::bark);
 
       bindn (&bark);
@@ -121,7 +121,7 @@ struct foo {
 
       bindb (&bark);
       bindb (&barT::bark); // { dg-error "ambiguous" }
-      // { dg-message "candidate" "candidate note" { target *-*-* } 123 }
+      // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 123 }
     }
   };
 
index 454acc63149caf9b5be0c9b0199a72331f0e1dfb..064554dfe71f661071a64073e14d8dc2b7cfed01 100644 (file)
@@ -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 )
index 44cbce938d74d96e4f41f5226d227f608a5fe505..e315a1a0902ca2fecf51b1f8795891e431269a70 100644 (file)
@@ -26,5 +26,5 @@ int main()
 {
   s<int>::t y;
   cout << y; // { dg-error "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 28 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 28 }
 }
index d86ea06bcd07f4c4d40002f71f073dccf9833792..b855569088fb14463c4979ed70df5b3f91858bc4 100644 (file)
@@ -9,6 +9,6 @@ A a;  // { dg-error "incomplete type" }
 
 void bar()
 {
-  foo<a>();  // { dg-error "no matching function" }
+  foo<a>();  // { dg-error "(no matching function|could not convert)" }
   // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
 }
index 9a03c9a7b98e09cae2dbd258bc4995fbcedfb88d..d842076bd80afad01c3ee8db61fee48eac5bad06 100644 (file)
@@ -5,6 +5,6 @@ template <typename T> void foo() {} // { dg-message "note" }
 
 int main () {
   struct S {};
-  foo<S> (); // { dg-error "match" } 
+  foo<S> (); // { dg-error "(match|template argument for|trying to instantiate)" } 
   // { dg-message "candidate" "candidate note" { target *-*-* } 8 }
 }
index 777349a195329e3e77fcc142e778e6e294619330..3eb828fd7118fae50efa812fa9f1a94cb57d040c 100644 (file)
@@ -5,7 +5,7 @@ template <class T> struct PCVector2 // { dg-message "note" }
     PCVector2<T> operator- (const PCVector2<T> &ov) const 
        { 
          return PCVector2<T>(ov.xFIELD, ov.yFIELD); // { dg-error "matching" }
-         // { dg-message "candidate" "candidate note" { target *-*-* } 7 }
+         // { dg-message "(candidate|expects 1 argument, 2 provided|cannot convert)" "candidate note" { target *-*-* } 7 }
        }
 
     T xFIELD, yFIELD;
index 35be778765a4eeece1497ce002c44e1aca54f2eb..46eef0a9ac7cdb10dcaa61d6d0827024bef13d2d 100644 (file)
@@ -5,6 +5,6 @@ template<operator+> void foo(); // { dg-error "before|non-function|template" }
 void bar()
 {
   foo();                        // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 7 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 7 }
 }
  
diff --git a/gcc/testsuite/g++.dg/template/overload12.C b/gcc/testsuite/g++.dg/template/overload12.C
new file mode 100644 (file)
index 0000000..656dcae
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile }
+
+struct S {int x; int y;};
+template<typename T>
+int foo(T a, T b) {return a + b;} // { dg-message "template" }
+template<typename T, typename T2>
+int foo(T a, T2& b, T2 c) {return a + b;}  // { dg-message "template" }
+int foo(char*, S&); // { dg-message "foo" }
+// { dg-message "candidate expects 2 arguments, 3 provided" "arity" { target *-*-* } 8 }
+
+int foo2(int x)
+{
+  S s={1,2};
+  char c;
+  foo(c, 2, c); // { dg-error "no matching function" }
+  // { dg-message "(candidate|deduced conflicting types for)" "candidate note" { target *-*-* } 15 }
+}
index 1919047360a3ac6134ac01bcff7c7a2f541d1cb0..5f03580c1b20cb69f756435452334e4ad67bcb7a 100644 (file)
@@ -7,7 +7,7 @@
 
 struct A {};
 
-template <typename T> T A::* Foo (); // { dg-message "note" }
+template <typename T> T A::* Foo (); // { dg-error "reference" }
 
 void Baz ()
 {
index e39ca6b76aac520c2377334e4b625ec6cbce21bc..c9e103114dd7f7d4feed2dc886cbb9f3217b77f2 100644 (file)
@@ -8,7 +8,7 @@ template<int T> struct cl {
   const static int value = T;
 };
 
-template<int I> void fn (char (*) [cl<I>::value] = 0 ); // { dg-message "note" }
+template<int I> void fn (char (*) [cl<I>::value] = 0 ); // { dg-error "zero-size array" }
 
 void foo (void)
 {
index 861d187d4db7f089927afc94e67648ad580966d8..46762ae21aff53ad7cbf326aa0ef874de279c15c 100644 (file)
@@ -18,12 +18,12 @@ void f4(T, C<5>);           // { dg-message "note" }
 template<int N> struct X {};
 void g() {
   f1(5l, X<5>()); // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 20 }
+  // { dg-message "(candidate|inconsistent with)" "candidate note" { target *-*-* } 20 }
   f2(X<5>(), 5);
   f3(X<5>(), 5l); // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 23 }
+  // { dg-message "(candidate|inconsistent with)" "candidate note" { target *-*-* } 23 }
   f4(5, X<5>());
   f4(5l, X<5>()); // { dg-error "no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 26 }
+  // { dg-message "(candidate|inconsistent with)" "candidate note" { target *-*-* } 26 }
   f4((short)5, X<5>());
 }
index 8dc434b7577205a2058277687968a6cdd9a6a0c7..7f2fd534624b30d42d8641580686871911029344 100644 (file)
@@ -26,34 +26,34 @@ void cvFunction(void (CLASS::* method)() const volatile) {} // { dg-message "not
 int main() {
   mFunction(&MyClass::mMethod);
   mFunction(&MyClass::cMethod);    // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 28 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 28 }
   mFunction(&MyClass::vMethod);    // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 30 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 30 }
   mFunction(&MyClass::cvMethod);   // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 32 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 32 }
 
   cFunction(&MyClass::mMethod);    // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 35 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 35 }
   cFunction(&MyClass::cMethod);
   cFunction(&MyClass::vMethod);    // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 38 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 38 }
   cFunction(&MyClass::cvMethod);   // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 40 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 40 }
 
   vFunction(&MyClass::mMethod);    // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 43 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 43 }
   vFunction(&MyClass::cMethod);    // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 45 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 45 }
   vFunction(&MyClass::vMethod);
   vFunction(&MyClass::cvMethod);   // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 48 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 48 }
 
   cvFunction(&MyClass::mMethod);   // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 51 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 51 }
   cvFunction(&MyClass::cMethod);   // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 53 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 53 }
   cvFunction(&MyClass::vMethod);   // { dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 55 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 55 }
   cvFunction(&MyClass::cvMethod);
 
   return 0;
index ed6b31c31c46ce7f6ec2a4cb6c677e69092cca43..25606dc4af885f26b6d3ff7f4cf4e6eb98f0aac6 100644 (file)
@@ -20,7 +20,7 @@ struct B
     C (U t)
     {
       A a;
-      A b = foo (this, a, t); // { dg-error "no matching function" }
+      A b = foo (this, a, t); // { dg-error "(no matching function|is not a)" }
       // { dg-message "candidate" "candidate note" { target *-*-* } 23 }
     }
   } c;
index b12ecb29b215b60d997072a3efb7735ce0350d30..551c96ebb9fedc8915164f6fa7c70db8c64d2b67 100644 (file)
@@ -19,5 +19,5 @@ void Bar ()
   Foo3 (&Baz);
 
   Foo3 (&Baz, &Baz); // { dg-error "no matching function" "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 21 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 21 }
 }
index 2bfa56303da9c85701fb48fe7d666b397d405206..88d9fd9baa0230adb9c1aed3950651d416963f67 100644 (file)
@@ -11,5 +11,5 @@ int main()
 {
   Foo (f);
   Baz (f); // { dg-error "no matching function" "" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 13 }
 }
index 40f6b9271fc5082d132a8e734649120c7c12bfcf..f06f83a8d1b722877388ea76fe3d599f9d691ebb 100644 (file)
@@ -14,5 +14,5 @@ const X *x;
  
 int main () { 
   f (*x, &X::g);  // {  dg-error "no matching function" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 16 }
 } 
index 6ae78d9003f58c98e978168545100a92a435c466..4ba11049b5ad1bf4940e45f7866d34cf1acb6215 100644 (file)
@@ -7,5 +7,5 @@ void bar()
   int i;
   int A[i][i]; 
   foo(A); // { dg-error "" } 
-  // { dg-message "candidate" "candidate note" { target *-*-* } 9 }
+  // { dg-message "(candidate|not a valid template argument)" "candidate note" { target *-*-* } 9 }
 }
index a22615dce6291a8da35bf6f564a86cfaf971ab07..e3bff80e610755f5d541a78eb8a09ac12b066041 100644 (file)
@@ -278,7 +278,7 @@ SetLD<T>::remove(const T& item)
     Vix x;
     for (first(x); 0 != x && this->REMOVE_CURRENT != a; next(x, a))
        a = operator()(x) == item ? this->REMOVE_CURRENT: this->NORMAL; // { dg-error "" } .*
-    // { dg-message "candidate" "candidate note" { target *-*-* } 280 }
+    // { dg-message "(candidate|not derived from)" "candidate note" { target *-*-* } 280 }
 }
 template<class T>
 bool
@@ -287,7 +287,7 @@ SetLD<T>::contains(const T& item) const
     Vix x;
     for (first(x); 0 != x; next(x)) {
        if (operator()(x) == item)// { dg-error "" } .*
-         // { dg-message "candidate" "candidate note" { target *-*-* } 289 }
+         // { dg-message "(candidate|not derived from)" "candidate note" { target *-*-* } 289 }
            return TRUE;
     }
     return FALSE;
index 2cfed93084de9e60390bb6570674f38712a0e3b4..81ed85a28ef5c2f2b0b528419d7a454149727482 100644 (file)
@@ -11,5 +11,5 @@ void f(unsigned int n) {
   int x[n];
 
   asize(x); // { dg-error "" } no matching function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 13 }
+  // { dg-message "(candidate|not a valid template argument)" "candidate note" { target *-*-* } 13 }
 }
index 1aad62132e1facef9bad158cc4160069d7066170..747af9b409036d32e2b7b7a95c03754344aec61b 100644 (file)
@@ -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 ); };
index 560370a8b48797e6090b1ba5c28d2d03aadefb78..c27d131238174d3b2a4cc5da8900f6d6fe6381b5 100644 (file)
@@ -1,6 +1,6 @@
 // { dg-do assemble  }
 template <int I>
-void f(int i);                 // { dg-message "note" }
+void f(int i);                 // { dg-message "void f" }
 
 void g()
 {
index 1213a1511d3df1f477d03880b4543554775abad3..b97c1cd02237a75528c768f6711ea3f5ffeb75a0 100644 (file)
@@ -15,5 +15,5 @@ void g() {
   
   f<0>(s0, s2);
   f(s0, s2); // { dg-error "" } no matching function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
+  // { dg-message "(candidate|deduced conflicting types|ambiguous base class)" "candidate note" { target *-*-* } 17 }
 }
index 0dcc65f6fac960d6710f8a4b0dbfa15f5921654d..06d22d5197a73bcef45c328821ac5d918f651d58 100644 (file)
@@ -9,5 +9,5 @@ void foo(S<J + 2>);             // { dg-message "note" }
 void bar()
 {
   foo(S<3>()); // { dg-error "" } no way to deduce J from this.
-  // { dg-message "candidate" "candidate note" { target *-*-* } 11 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 11 }
 }
index 85d3e7378cadd06155cf9183251159586f371c99..8802e983b677614fd5da8ef617763d9c69d8c417 100644 (file)
@@ -13,9 +13,9 @@ public:
 };
 
 template <void (A::*)() >
-void g() {}                    // { dg-message "note" }
+void g() {}                    // { dg-message "void g" }
 template <int A::*>
-void h() {}                    // { dg-message "note" }
+void h() {}                    // { dg-message "void h" }
 
 
 int main() {
index df7112ad0d0ecf8ac937f2f28c94214a89bae635..96e8cf911607117ea09f149c1fa5229ed19764fd 100644 (file)
@@ -14,9 +14,9 @@ template void g(int i, int j);
 void h()
 {
   f(3, 'c'); // { dg-error "" } no matching function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 16 }
+  // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 16 }
   g(3, 'c'); // { dg-error "" } no matching function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
+  // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 18 }
 }
 
 
index fc19c3cf53595242ea04e52958fe789c2b3f6ec6..b8f6673fa0b3b3eb60744ca9317b0e888c416128 100644 (file)
@@ -25,9 +25,9 @@ void h()
 {
   S1 s1;
   s1.f(3, 'c'); // { dg-error "" } no matching function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 27 }
+  // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 27 }
 
   S2<char> s2;
   s2.f(3, 'c'); // { dg-error "" } no matching function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 31 }
+  // { dg-message "(candidate|deduced conflicting types)" "candidate note" { target *-*-* } 31 }
 }
index 6dd9961088d17c25515f005d4f8bc9a1c031630a..9285b21c2ee860c46fe23e854ae256dff7828172 100644 (file)
@@ -8,6 +8,6 @@ int
 main ()
 {
   f (g);                       // { dg-error "" } ambiguous unification
-  // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+  // { dg-message "(candidate|deduce template parameter)" "candidate note" { target *-*-* } 10 }
   return 0;
 }
index 0e5c0349544d426159c683c8d1903a826c543231..a6f76744d228a30b605d8ad566e460d0a73f4115 100644 (file)
@@ -19,7 +19,7 @@ template<> void fn<int &>() {} // ok, specialize A
 template<> void fn<void ()>() {} // ok, specialize A
 
 // now make sure we moan when we really should
-template<class T> void foo(T const *){} // { dg-message "note" }
+template<class T> void foo(T const *){} // { dg-error "pointer to reference" }
 
 void f()
 {
index 320926092f087e0c28c0f2a9059952ca58264ab7..3a86d977ec3a3f4ecbc7e300acff09faf0cf6115 100644 (file)
@@ -16,6 +16,6 @@ void Foo (float);     // { dg-message "note" } candidate
 void baz (int **p1)
 {
   Foo (p1);   // { dg-error "match" } no such function
-  // { dg-message "candidate" "candidate note" { target *-*-* } 18 }
+  // { dg-message "(candidate|incompatible cv-qualifiers)" "candidate note" { target *-*-* } 18 }
   Bar (p1);   // OK
 }
index c5620316e9ca860c907c0653903a03582bda1e5f..410a336911821b65f7041920fc1bf94859a213ee 100644 (file)
@@ -15,5 +15,5 @@
     void f()
     {
       extent(b);  // { dg-error "" } no matching function
-      // { dg-message "candidate" "candidate note" { target *-*-* } 17 }
+      // { dg-message "(candidate|mismatched types)" "candidate note" { target *-*-* } 17 }
     }