[cfe-commits] r103339 - in /cfe/trunk: include/clang/AST/TemplateBase.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/TemplateBase.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp test/SemaTemplate/overload-candidates.cpp

Douglas Gregor dgregor at apple.com
Sat May 8 10:41:32 PDT 2010


Author: dgregor
Date: Sat May  8 12:41:32 2010
New Revision: 103339

URL: http://llvm.org/viewvc/llvm-project?rev=103339&view=rev
Log:
When printing a non-viable overload candidate that failed due to
conflicting deduced template argument values, give a more specific
reason along with those values, e.g.,

test/SemaTemplate/overload-candidates.cpp:4:10: note: candidate template
      ignored: deduced conflicting types for parameter 'T' ('int' vs. 'long')
const T& min(const T&, const T&); 
         ^



Added:
    cfe/trunk/test/SemaTemplate/overload-candidates.cpp   (with props)
Modified:
    cfe/trunk/include/clang/AST/TemplateBase.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/TemplateBase.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaOverload.h
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp

Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=103339&r1=103338&r2=103339&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Sat May  8 12:41:32 2010
@@ -28,6 +28,7 @@
 namespace clang {
 
 class Decl;
+class DiagnosticBuilder;
 class Expr;
 class TypeSourceInfo;
 
@@ -473,6 +474,9 @@
   }
 };
 
-}
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+                                    const TemplateArgument &Arg);
+  
+} // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=103339&r1=103338&r2=103339&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat May  8 12:41:32 2010
@@ -1060,7 +1060,10 @@
     "candidate template ignored: failed template argument deduction">;
 def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
     "couldn't infer template argument %0">;
-
+def note_ovl_candidate_inconsistent_deduction : Note<
+    "candidate template ignored: deduced conflicting %select{types|values|"
+    "templates}0 for parameter %1 (%2 vs. %3)">;
+    
 // 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/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=103339&r1=103338&r2=103339&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Sat May  8 12:41:32 2010
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/Diagnostic.h"
 
 using namespace clang;
 
@@ -119,3 +120,42 @@
   // Silence bonus gcc warning.
   return SourceRange();
 }
+
+const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
+                                           const TemplateArgument &Arg) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    return DB;
+      
+  case TemplateArgument::Type:
+    return DB << Arg.getAsType();
+      
+  case TemplateArgument::Declaration:
+    return DB << Arg.getAsDecl();
+      
+  case TemplateArgument::Integral:
+    return DB << Arg.getAsIntegral()->toString(10);
+      
+  case TemplateArgument::Template:
+    return DB << Arg.getAsTemplate();
+      
+  case TemplateArgument::Expression: {
+    // This shouldn't actually ever happen, so it's okay that we're
+    // regurgitating an expression here.
+    // FIXME: We're guessing at LangOptions!
+    llvm::SmallString<32> Str;
+    llvm::raw_svector_ostream OS(Str);
+    LangOptions LangOpts;
+    LangOpts.CPlusPlus = true;
+    PrintingPolicy Policy(LangOpts);
+    Arg.getAsExpr()->printPretty(OS, 0, Policy);
+    return DB << OS.str();
+  }
+      
+  case TemplateArgument::Pack:
+    // FIXME: Format arguments in a list!
+    return DB << "<parameter pack>";
+  }
+  
+  return DB;
+}

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=103339&r1=103338&r2=103339&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Sat May  8 12:41:32 2010
@@ -275,7 +275,166 @@
   new (&conversions()) ConversionSet(O.conversions());
 }
 
+namespace {
+  // Structure used by OverloadCandidate::DeductionFailureInfo to store
+  // template parameter and template argument information.
+  struct DFIParamWithArguments {
+    TemplateParameter Param;
+    TemplateArgument FirstArg;
+    TemplateArgument SecondArg;
+  };
+}
+  
+/// \brief Convert from Sema's representation of template deduction information
+/// to the form used in overload-candidate information.
+OverloadCandidate::DeductionFailureInfo
+static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
+                                const Sema::TemplateDeductionInfo &Info) {
+  OverloadCandidate::DeductionFailureInfo Result;
+  Result.Result = static_cast<unsigned>(TDK);
+  Result.Data = 0;
+  switch (TDK) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+    break;
+      
+  case Sema::TDK_Incomplete:
+    Result.Data = Info.Param.getOpaqueValue();
+    break;
+      
+  // Unhandled
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals: {
+    DFIParamWithArguments *Saved = new DFIParamWithArguments;
+    Saved->Param = Info.Param;
+    Saved->FirstArg = Info.FirstArg;
+    Saved->SecondArg = Info.SecondArg;
+    Result.Data = Saved;
+    break;
+  }
+      
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    break;  
+  }
+  
+  return Result;
+}
+
+void OverloadCandidate::DeductionFailureInfo::Destroy() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Incomplete:
+    break;
+      
+  // Unhandled
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals:
+    delete static_cast<DFIParamWithArguments*>(Data);
+    Data = 0;
+    break;
+      
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+}
+  
+TemplateParameter 
+OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+    return TemplateParameter();
+    
+  case Sema::TDK_Incomplete:
+    return TemplateParameter::getFromOpaqueValue(Data);    
 
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals:
+    return static_cast<DFIParamWithArguments*>(Data)->Param;
+      
+  // Unhandled
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+  
+  return TemplateParameter();
+}
+  
+const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Incomplete:
+    return 0;
+
+  // Unhandled
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals:
+    return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;      
+
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+  
+  return 0;
+}    
+
+const TemplateArgument *
+OverloadCandidate::DeductionFailureInfo::getSecondArg() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+  case Sema::TDK_Success:
+  case Sema::TDK_InstantiationDepth:
+  case Sema::TDK_Incomplete:
+    return 0;
+
+  // Unhandled
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals:
+    return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
+
+  case Sema::TDK_SubstitutionFailure:
+  case Sema::TDK_NonDeducedMismatch:
+  case Sema::TDK_TooManyArguments:
+  case Sema::TDK_TooFewArguments:
+  case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_FailedOverloadResolution:
+    break;
+  }
+  
+  return 0;
+}
+
+void OverloadCandidateSet::clear() {
+  for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
+    if (C->FailureKind == ovl_fail_bad_deduction)
+      C->DeductionFailure.Destroy();
+  }
+       
+  inherited::clear();
+  Functions.clear();
+}
+  
 // IsOverload - Determine whether the given New declaration is an
 // overload of the declarations in Old. This routine returns false if
 // New and Old cannot be overloaded, e.g., if New has the same
@@ -3028,7 +3187,7 @@
     }
   }
 }
-
+  
 /// \brief Add a C++ member function template as a candidate to the candidate
 /// set, using template argument deduction to produce an appropriate member
 /// function template specialization.
@@ -3109,10 +3268,7 @@
     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();
+    Candidate.DeductionFailure = MakeDeductionFailureInfo(Result, Info);
     return;
   }
 
@@ -4929,9 +5085,7 @@
                           Expr **Args, unsigned NumArgs) {
   FunctionDecl *Fn = Cand->Function; // pattern
 
-  TemplateParameter Param = TemplateParameter::getFromOpaqueValue(
-                                   Cand->DeductionFailure.TemplateParameter);
-
+  TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
   switch (Cand->DeductionFailure.Result) {
   case Sema::TDK_Success:
     llvm_unreachable("TDK_success while diagnosing bad deduction");
@@ -4947,11 +5101,29 @@
     return;
   }
 
+  case Sema::TDK_Inconsistent:
+  case Sema::TDK_InconsistentQuals: {
+    NamedDecl *ParamD;
+    int which = 0;
+    if ((ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()))
+      which = 0;
+    else if ((ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()))
+      which = 1;
+    else {
+      ParamD = Param.get<TemplateTemplateParmDecl*>();
+      which = 2;
+    }
+    
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
+      << which << ParamD->getDeclName() 
+      << *Cand->DeductionFailure.getFirstArg()
+      << *Cand->DeductionFailure.getSecondArg();
+    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:

Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=103339&r1=103338&r2=103339&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Sat May  8 12:41:32 2010
@@ -16,7 +16,9 @@
 #define LLVM_CLANG_SEMA_OVERLOAD_H
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/TemplateBase.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -529,8 +531,24 @@
       // A Sema::TemplateDeductionResult.
       unsigned Result;
 
-      // A TemplateParameter.
-      void *TemplateParameter;
+      /// \brief Opaque pointer containing additional data about
+      /// this deduction failure.
+      void *Data;
+      
+      /// \brief Retrieve the template parameter this deduction failure
+      /// refers to, if any.
+      TemplateParameter getTemplateParameter();
+      
+      /// \brief Return the first template argument this deduction failure
+      /// refers to, if any.
+      const TemplateArgument *getFirstArg();
+
+      /// \brief Return the second template argument this deduction failure
+      /// refers to, if any.
+      const TemplateArgument *getSecondArg();
+      
+      /// \brief Free any memory associated with this deduction failure.
+      void Destroy();
     };
 
     union {
@@ -574,10 +592,9 @@
     }
 
     /// \brief Clear out all of the candidates.
-    void clear() {
-      inherited::clear();
-      Functions.clear();
-    }
+    void clear();
+    
+    ~OverloadCandidateSet() { clear(); }
   };
 } // end namespace clang
 

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=103339&r1=103338&r2=103339&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 Sat May  8 12:41:32 2010
@@ -16,7 +16,8 @@
 }
 
 // TODO: this diagnostic can and should improve
-template<typename T> void f2(T*, T*); // expected-note 2 {{candidate template ignored: failed template argument deduction}}
+template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: failed template argument deduction}} \
+// expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'float')}}
 
 struct ConvToIntPtr {
   operator int*() const;

Modified: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp?rev=103339&r1=103338&r2=103339&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp Sat May  8 12:41:32 2010
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
 namespace test0 {
-  template<class T> void apply(T x, void (*f)(T)) { f(x); } // expected-note 2 {{failed template argument deduction}}\
+  template<class T> void apply(T x, void (*f)(T)) { f(x); } // expected-note 2 {{candidate template ignored: deduced conflicting types for parameter 'T'}}\
   // expected-note {{no overload of 'temp2' matching 'void (*)(int)'}}
 
   template<class A> void temp(A);

Added: cfe/trunk/test/SemaTemplate/overload-candidates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/overload-candidates.cpp?rev=103339&view=auto
==============================================================================
--- cfe/trunk/test/SemaTemplate/overload-candidates.cpp (added)
+++ cfe/trunk/test/SemaTemplate/overload-candidates.cpp Sat May  8 12:41:32 2010
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<typename T>
+const T& min(const T&, const T&); // expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'long')}}
+
+void test_min() {
+  (void)min(1, 2l); // expected-error{{no matching function for call to 'min'}}
+}

Propchange: cfe/trunk/test/SemaTemplate/overload-candidates.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/SemaTemplate/overload-candidates.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/SemaTemplate/overload-candidates.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list