]> granicus.if.org Git - clang/commitdiff
Note that an overload candidate was non-viable because template argument
authorJohn McCall <rjmccall@apple.com>
Mon, 1 Feb 2010 18:53:26 +0000 (18:53 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 1 Feb 2010 18:53:26 +0000 (18:53 +0000)
deduction failed.  Right now there's a very vague diagnostic for most cases
and a good diagnostic for incomplete deduction.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
lib/Sema/SemaOverload.h
test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp
test/SemaTemplate/recursive-template-instantiation.cpp

index c4ce6affc6d2b8db68d49e1f73b4a087193a65fa..7da597de6fca38017153dd54618c5d4bfd8e661d 100644 (file)
@@ -925,6 +925,12 @@ def note_ovl_candidate : Note<"candidate "
     "is the implicit default constructor|"
     "is the implicit copy constructor|"
     "is the implicit copy assignment operator}0%1">;
+
+def note_ovl_candidate_bad_deduction : Note<
+    "candidate template ignored: failed template argument deduction">;
+def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
+    "couldn't infer template argument %0">;
+
 // Note that we don't treat templates differently for this diagnostic.
 def note_ovl_candidate_arity : Note<"candidate "
     "%select{function|function|constructor|function|function|constructor|"
index 24cad2a9c574c7463b02166b9fa9add307dff76d..1eb5b38889e99f589f0caf1e3003968aeb01585c 100644 (file)
@@ -2742,10 +2742,6 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
   if (TemplateDeductionResult Result
         = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs,
                                   Args, NumArgs, Specialization, Info)) {
-    // FIXME: Record what happened with template argument deduction, so
-    // that we can give the user a beautiful diagnostic.
-    (void) Result;
-
     CandidateSet.push_back(OverloadCandidate());
     OverloadCandidate &Candidate = CandidateSet.back();
     Candidate.Function = FunctionTemplate->getTemplatedDecl();
@@ -2754,6 +2750,10 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
     Candidate.FailureKind = ovl_fail_bad_deduction;
     Candidate.IsSurrogate = false;
     Candidate.IgnoreObjectArgument = false;
+
+    // TODO: record more information about failed template arguments
+    Candidate.DeductionFailure.Result = Result;
+    Candidate.DeductionFailure.TemplateParameter = Info.Param.getOpaqueValue();
     return;
   }
 
@@ -4556,6 +4556,58 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
     << (unsigned) FnKind << Description << mode << modeCount << NumFormalArgs;
 }
 
+/// Diagnose a failed template-argument deduction.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+                          Expr **Args, unsigned NumArgs) {
+  FunctionDecl *Fn = Cand->Function; // pattern
+
+  TemplateParameter Param = TemplateParameter::getFromOpaqueValue(
+                                   Cand->DeductionFailure.TemplateParameter);
+
+  switch (Cand->DeductionFailure.Result) {
+  case Sema::TDK_Success:
+    llvm_unreachable("TDK_success while diagnosing bad deduction");
+
+  case Sema::TDK_Incomplete: {
+    NamedDecl *ParamD;
+    (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
+    (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
+    (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
+    assert(ParamD && "no parameter found for incomplete deduction result");
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
+      << ParamD->getDeclName();
+    return;
+  }
+
+  // TODO: diagnose these individually, then kill off
+  // note_ovl_candidate_bad_deduction, which is uselessly vague.
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals:
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
+    return;
+  }
+}
+
+/// Generates a 'note' diagnostic for an overload candidate.  We've
+/// already generated a primary error at the call site.
+///
+/// It really does need to be a single diagnostic with its caret
+/// pointed at the candidate declaration.  Yes, this creates some
+/// major challenges of technical writing.  Yes, this makes pointing
+/// out problems with specific arguments quite awkward.  It's still
+/// better than generating twenty screens of text for every failed
+/// overload.
+///
+/// It would be great to be able to express per-candidate problems
+/// more richly for those diagnostic clients that cared, but we'd
+/// still have to be just as careful with the default diagnostics.
 void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
                            Expr **Args, unsigned NumArgs) {
   FunctionDecl *Fn = Cand->Function;
@@ -4582,6 +4634,8 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
     return DiagnoseArityMismatch(S, Cand, NumArgs);
 
   case ovl_fail_bad_deduction:
+    return DiagnoseBadDeduction(S, Cand, Args, NumArgs);
+
   case ovl_fail_trivial_conversion:
   case ovl_fail_bad_final_conversion:
     return S.NoteOverloadCandidate(Fn);
index 66ed2259bd287e1db840d4bd4be1684a88cc521d..cc26277825f2ddd17ee2291ae3533b2cac0f99b5 100644 (file)
@@ -465,11 +465,25 @@ namespace clang {
       return AccessSpecifier(Access);
     }
 
-    /// FinalConversion - For a conversion function (where Function is
-    /// a CXXConversionDecl), the standard conversion that occurs
-    /// after the call to the overload candidate to convert the result
-    /// of calling the conversion function to the required type.
-    StandardConversionSequence FinalConversion;
+    /// A structure used to record information about a failed
+    /// template argument deduction.
+    struct DeductionFailureInfo {
+      // A Sema::TemplateDeductionResult.
+      unsigned Result;
+
+      // A TemplateParameter.
+      void *TemplateParameter;
+    };
+
+    union {
+      DeductionFailureInfo DeductionFailure;
+      
+      /// FinalConversion - For a conversion function (where Function is
+      /// a CXXConversionDecl), the standard conversion that occurs
+      /// after the call to the overload candidate to convert the result
+      /// of calling the conversion function to the required type.
+      StandardConversionSequence FinalConversion;
+    };
 
     /// hasAmbiguousConversion - Returns whether this overload
     /// candidate requires an ambiguous conversion or not.
index 8fb736ca0313e26a6d4942aa545a23a4a454bac8..95f9640a0b435cd7b41f8e7c5605542cc760cca6 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate function}}
+template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate template ignored: couldn't infer template argument 'X'}}
 
 void g() {
   f<int,char*,double>("aa",3.0); 
index bcfb71c987ebfe105b9567e50b514bc0e3176e2e..1b7310f00055f2aaf58786f3cf3c451faa2a1bda 100644 (file)
@@ -15,7 +15,8 @@ void test_f1(int *ip, float fv) {
   f1(ip, fv);
 }
 
-template<typename T> void f2(T*, T*); // expected-note 2 {{candidate function}}
+// TODO: this diagnostic can and should improve
+template<typename T> void f2(T*, T*); // expected-note 2 {{candidate template ignored: failed template argument deduction}}
 
 struct ConvToIntPtr {
   operator int*() const;
index 0ddedaf2354abb4f6a4e470c15271ca1f4e3cf58..d6a0b247dd452a316372f40d6f7ff0776a67f26e 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-template<typename T> void f(T* t) { // expected-note{{candidate function}}
+template<typename T> void f(T* t) { // expected-note{{failed template argument deduction}}
   f(*t); // expected-error{{no matching function}}\
          // expected-note 3{{requested here}}
 }