]> granicus.if.org Git - clang/commitdiff
Replace "failed template argument deduction" diagnostic with something useful
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 31 Jan 2013 04:03:12 +0000 (04:03 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 31 Jan 2013 04:03:12 +0000 (04:03 +0000)
in the one case where we've already factored out a reason code.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174036 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Overload.h
include/clang/Sema/TemplateDeduction.h
lib/Sema/SemaOverload.cpp
lib/Sema/SemaTemplateDeduction.cpp
test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp

index aa6bcd6aa33219326e5d66854f5a65afa16d9e80..f20bd06ce556c8ba0ab1871102c700d6be2ee635 100644 (file)
@@ -2331,6 +2331,9 @@ def note_ovl_candidate_substitution_failure : Note<
     "candidate template ignored: substitution failure%0%1">;
 def note_ovl_candidate_disabled_by_enable_if : Note<
     "candidate template ignored: disabled by %0%1">;
+def note_ovl_candidate_failed_overload_resolution : Note<
+    "candidate template ignored: couldn't resolve reference to overloaded "
+    "function %0">;
     
 // Note that we don't treat templates differently for this diagnostic.
 def note_ovl_candidate_arity : Note<"candidate "
index 305b0675481f11e870ec43c46135abb2fc6ca175..8a2cef73360c1082e13fac76935a35c02249d44b 100644 (file)
@@ -694,6 +694,10 @@ namespace clang {
       /// \brief Return the second template argument this deduction failure
       /// refers to, if any.
       const TemplateArgument *getSecondArg();
+
+      /// \brief Return the expression this deduction failure refers to,
+      /// if any.
+      Expr *getExpr();
       
       /// \brief Free any memory associated with this deduction failure.
       void Destroy();
index 5c69a922a91ff687c07f07f79fd7686139fb55ce..e9a1449dbb0c981ab0941110c13af154f50db30f 100644 (file)
@@ -47,7 +47,7 @@ class TemplateDeductionInfo {
 
 public:
   TemplateDeductionInfo(SourceLocation Loc)
-    : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false) { }
+    : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { }
 
   /// \brief Returns the location at which template argument is
   /// occurring.
@@ -150,6 +150,13 @@ public:
   ///
   /// FIXME: Finish documenting this.
   TemplateArgument SecondArg;
+
+  /// \brief The expression which caused a deduction failure.
+  ///
+  ///   TDK_FailedOverloadResolution: this argument is the reference to
+  //    an overloaded function which could not be resolved to a specific
+  //    function.
+  Expr *Expression;
 };
 
 }
index 22cb61eda390742c5886c5d417f5d9a5d40fabb1..dbab73983280c812078b57454db92bea317a08bd 100644 (file)
@@ -588,8 +588,11 @@ static MakeDeductionFailureInfo(ASTContext &Context,
     }
     break;
 
-  case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
+    Result.Data = Info.Expression;
+    break;
+
+  case Sema::TDK_NonDeducedMismatch:
     break;
   }
 
@@ -741,6 +744,15 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
   return 0;
 }
 
+Expr *
+OverloadCandidate::DeductionFailureInfo::getExpr() {
+  if (static_cast<Sema::TemplateDeductionResult>(Result) ==
+        Sema::TDK_FailedOverloadResolution)
+    return static_cast<Expr*>(Data);
+
+  return 0;
+}
+
 void OverloadCandidateSet::destroyCandidates() {
   for (iterator i = begin(), e = end(); i != e; ++i) {
     for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
@@ -8442,10 +8454,18 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
     return;
   }
 
+  case Sema::TDK_FailedOverloadResolution: {
+    OverloadExpr::FindResult R =
+        OverloadExpr::find(Cand->DeductionFailure.getExpr());
+    S.Diag(Fn->getLocation(),
+           diag::note_ovl_candidate_failed_overload_resolution)
+      << R.Expression->getName();
+    return;
+  }
+
   // TODO: diagnose these individually, then kill off
   // note_ovl_candidate_bad_deduction, which is uselessly vague.
   case Sema::TDK_NonDeducedMismatch:
-  case Sema::TDK_FailedOverloadResolution:
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
     MaybeEmitInheritedConstructorNote(S, Fn);
     return;
index a8de3a8de9e48744e78ccffaa185caeea780ab9b..003d0161e94fedde3adc04a5f984f9fa3a518848 100644 (file)
@@ -2879,7 +2879,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
 /// described in C++ [temp.deduct.call].
 ///
 /// \returns true if the caller should not attempt to perform any template
-/// argument deduction based on this P/A pair.
+/// argument deduction based on this P/A pair because the argument is an
+/// overloaded function set that could not be resolved.
 static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
                                           TemplateParameterList *TemplateParams,
                                                       QualType &ParamType,
@@ -2895,7 +2896,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
   if (ParamRefType) {
     QualType PointeeType = ParamRefType->getPointeeType();
 
-    // If the argument has incomplete array type, try to complete it's type.
+    // If the argument has incomplete array type, try to complete its type.
     if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
       ArgType = Arg->getType();
 
@@ -2993,8 +2994,8 @@ static bool hasDeducibleTemplateParameters(Sema &S,
 
 /// \brief Perform template argument deduction by matching a parameter type
 ///        against a single expression, where the expression is an element of
-///        an initializer list that was originally matched against the argument
-///        type.
+///        an initializer list that was originally matched against a parameter
+///        of type \c initializer_list\<ParamType\>.
 static Sema::TemplateDeductionResult
 DeduceTemplateArgumentByListElement(Sema &S,
                                     TemplateParameterList *TemplateParams,
@@ -3023,8 +3024,10 @@ DeduceTemplateArgumentByListElement(Sema &S,
   // For all other cases, just match by type.
   QualType ArgType = Arg->getType();
   if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType, 
-                                                ArgType, Arg, TDF))
+                                                ArgType, Arg, TDF)) {
+    Info.Expression = Arg;
     return Sema::TDK_FailedOverloadResolution;
+  }
   return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
                                             ArgType, Info, Deduced, TDF);
 }
index 4fd419dc748e232a16a7f18c67c764647c92d158..88571d671b0737a8afacf17951a82398aa1c48fa 100644 (file)
@@ -199,3 +199,12 @@ namespace initlist_of_array {
     f({{1,2},{3,4}});
   }
 }
+
+namespace init_list_deduction_failure {
+  void f();
+  void f(int);
+  template<typename T> void g(std::initializer_list<T>);
+  // expected-note@-1 {{candidate template ignored: couldn't resolve reference to overloaded function 'f'}}
+  void h() { g({f}); }
+  // expected-error@-1 {{no matching function for call to 'g'}}
+}