[cfe-commits] r94988 - in /cfe/trunk: 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

John McCall rjmccall at apple.com
Mon Feb 1 10:53:26 PST 2010


Author: rjmccall
Date: Mon Feb  1 12:53:26 2010
New Revision: 94988

URL: http://llvm.org/viewvc/llvm-project?rev=94988&view=rev
Log:
Note that an overload candidate was non-viable because template argument
deduction failed.  Right now there's a very vague diagnostic for most cases
and a good diagnostic for incomplete deduction.


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

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=94988&r1=94987&r2=94988&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Feb  1 12:53:26 2010
@@ -925,6 +925,12 @@
     "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|"

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=94988&r1=94987&r2=94988&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Feb  1 12:53:26 2010
@@ -2742,10 +2742,6 @@
   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 @@
     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 @@
     << (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 @@
     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);

Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=94988&r1=94987&r2=94988&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Mon Feb  1 12:53:26 2010
@@ -465,11 +465,25 @@
       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.

Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp?rev=94988&r1=94987&r2=94988&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp Mon Feb  1 12:53:26 2010
@@ -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); 

Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp?rev=94988&r1=94987&r2=94988&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp Mon Feb  1 12:53:26 2010
@@ -15,7 +15,8 @@
   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;

Modified: cfe/trunk/test/SemaTemplate/recursive-template-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/recursive-template-instantiation.cpp?rev=94988&r1=94987&r2=94988&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/recursive-template-instantiation.cpp (original)
+++ cfe/trunk/test/SemaTemplate/recursive-template-instantiation.cpp Mon Feb  1 12:53:26 2010
@@ -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}}
 }





More information about the cfe-commits mailing list