r186727 - Use function overloading instead of template specialization for diagnosis of bad template argument deductions.

Larisse Voufo lvoufo at google.com
Fri Jul 19 15:34:33 PDT 2013


Author: lvoufo
Date: Fri Jul 19 17:34:32 2013
New Revision: 186727

URL: http://llvm.org/viewvc/llvm-project?rev=186727&view=rev
Log:
Use function overloading instead of template specialization for diagnosis of bad template argument deductions.

Modified:
    cfe/trunk/include/clang/Sema/Overload.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/TemplateDeduction.h
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
    cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp
    cfe/trunk/test/CXX/over/over.over/p2.cpp
    cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp
    cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp
    cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm
    cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp
    cfe/trunk/test/SemaTemplate/function-template-specialization.cpp

Modified: cfe/trunk/include/clang/Sema/Overload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Overload.h (original)
+++ cfe/trunk/include/clang/Sema/Overload.h Fri Jul 19 17:34:32 2013
@@ -22,6 +22,7 @@
 #include "clang/AST/Type.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Sema/SemaFixItUtils.h"
+#include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Allocator.h"
@@ -656,53 +657,6 @@ namespace clang {
     /// \brief The number of call arguments that were explicitly provided,
     /// to be used while performing partial ordering of function templates.
     unsigned ExplicitCallArguments;
-    
-    /// A structure used to record information about a failed
-    /// template argument deduction.
-    struct DeductionFailureInfo {
-      /// A Sema::TemplateDeductionResult.
-      unsigned Result : 8;
-
-      /// \brief Indicates whether a diagnostic is stored in Diagnostic.
-      unsigned HasDiagnostic : 1;
-
-      /// \brief Opaque pointer containing additional data about
-      /// this deduction failure.
-      void *Data;
-
-      /// \brief A diagnostic indicating why deduction failed.
-      union {
-        void *Align;
-        char Diagnostic[sizeof(PartialDiagnosticAt)];
-      };
-
-      /// \brief Retrieve the diagnostic which caused this deduction failure,
-      /// if any.
-      PartialDiagnosticAt *getSFINAEDiagnostic();
-      
-      /// \brief Retrieve the template parameter this deduction failure
-      /// refers to, if any.
-      TemplateParameter getTemplateParameter();
-      
-      /// \brief Retrieve the template argument list associated with this
-      /// deduction failure, if any.
-      TemplateArgumentList *getTemplateArgumentList();
-      
-      /// \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 Return the expression this deduction failure refers to,
-      /// if any.
-      Expr *getExpr();
-      
-      /// \brief Free any memory associated with this deduction failure.
-      void Destroy();
-    };
 
     union {
       DeductionFailureInfo DeductionFailure;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jul 19 17:34:32 2013
@@ -176,6 +176,8 @@ namespace clang {
   class VisibilityAttr;
   class VisibleDeclConsumer;
   class IndirectFieldDecl;
+  struct DeductionFailureInfo;
+  class TemplateSpecCandidateSet;
 
 namespace sema {
   class AccessedEntity;
@@ -5773,16 +5775,15 @@ public:
                                                    SourceLocation Loc,
                                            TemplatePartialOrderingContext TPOC,
                                                    unsigned NumCallArguments);
-  UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin,
-                                           UnresolvedSetIterator SEnd,
-                                           TemplatePartialOrderingContext TPOC,
-                                           unsigned NumCallArguments,
-                                           SourceLocation Loc,
-                                           const PartialDiagnostic &NoneDiag,
-                                           const PartialDiagnostic &AmbigDiag,
-                                        const PartialDiagnostic &CandidateDiag,
-                                        bool Complain = true,
-                                        QualType TargetType = QualType());
+  UnresolvedSetIterator
+  getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd,
+                     TemplateSpecCandidateSet &FailedCandidates,
+                     TemplatePartialOrderingContext TPOC,
+                     unsigned NumCallArguments, SourceLocation Loc,
+                     const PartialDiagnostic &NoneDiag,
+                     const PartialDiagnostic &AmbigDiag,
+                     const PartialDiagnostic &CandidateDiag,
+                     bool Complain = true, QualType TargetType = QualType());
 
   ClassTemplatePartialSpecializationDecl *
   getMoreSpecializedPartialSpecialization(
@@ -7744,6 +7745,10 @@ public:
   }
 };
 
+DeductionFailureInfo
+MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK,
+                         sema::TemplateDeductionInfo &Info);
+
 }  // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/Sema/TemplateDeduction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TemplateDeduction.h?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/TemplateDeduction.h (original)
+++ cfe/trunk/include/clang/Sema/TemplateDeduction.h Fri Jul 19 17:34:32 2013
@@ -20,6 +20,7 @@
 namespace clang {
 
 class TemplateArgumentList;
+class Sema;
 
 namespace sema {
 
@@ -162,7 +163,124 @@ public:
   Expr *Expression;
 };
 
-}
-}
+} // end namespace sema
+
+/// A structure used to record information about a failed
+/// template argument deduction, for diagnosis.
+struct DeductionFailureInfo {
+  /// A Sema::TemplateDeductionResult.
+  unsigned Result : 8;
+
+  /// \brief Indicates whether a diagnostic is stored in Diagnostic.
+  unsigned HasDiagnostic : 1;
+
+  /// \brief Opaque pointer containing additional data about
+  /// this deduction failure.
+  void *Data;
+
+  /// \brief A diagnostic indicating why deduction failed.
+  union {
+    void *Align;
+    char Diagnostic[sizeof(PartialDiagnosticAt)];
+  };
+
+  /// \brief Retrieve the diagnostic which caused this deduction failure,
+  /// if any.
+  PartialDiagnosticAt *getSFINAEDiagnostic();
+
+  /// \brief Retrieve the template parameter this deduction failure
+  /// refers to, if any.
+  TemplateParameter getTemplateParameter();
+
+  /// \brief Retrieve the template argument list associated with this
+  /// deduction failure, if any.
+  TemplateArgumentList *getTemplateArgumentList();
+
+  /// \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 Return the expression this deduction failure refers to,
+  /// if any.
+  Expr *getExpr();
+
+  /// \brief Free any memory associated with this deduction failure.
+  void Destroy();
+};
+
+/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
+/// which keeps track of template argument deduction failure info, when
+/// handling explicit specializations (and instantiations) of templates
+/// beyond function overloading.
+/// For now, assume that the candidates are non-matching specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidate.
+struct TemplateSpecCandidate {
+  /// Specialization - The actual specialization that this candidate
+  /// represents. When NULL, this may be a built-in candidate.
+  Decl *Specialization;
+
+  /// Template argument deduction info
+  DeductionFailureInfo DeductionFailure;
+
+  void set(Decl *Spec, DeductionFailureInfo Info) {
+    Specialization = Spec;
+    DeductionFailure = Info;
+  }
+
+  /// Diagnose a template argument deduction failure.
+  void NoteDeductionFailure(Sema &S);
+};
+
+/// TemplateSpecCandidateSet - A set of generalized overload candidates,
+/// used in template specializations.
+/// TODO: In the future, we may need to unify/generalize this with
+/// OverloadCandidateSet.
+class TemplateSpecCandidateSet {
+  SmallVector<TemplateSpecCandidate, 16> Candidates;
+  SourceLocation Loc;
+
+  TemplateSpecCandidateSet(
+      const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
+  void operator=(const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
+
+  void destroyCandidates();
+
+public:
+  TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {}
+  ~TemplateSpecCandidateSet() { destroyCandidates(); }
+
+  SourceLocation getLocation() const { return Loc; }
+
+  /// \brief Clear out all of the candidates.
+  /// TODO: This may be unnecessary.
+  void clear();
+
+  typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
+  iterator begin() { return Candidates.begin(); }
+  iterator end() { return Candidates.end(); }
+
+  size_t size() const { return Candidates.size(); }
+  bool empty() const { return Candidates.empty(); }
+
+  /// \brief Add a new candidate with NumConversions conversion sequence slots
+  /// to the overload set.
+  TemplateSpecCandidate &addCandidate() {
+    Candidates.push_back(TemplateSpecCandidate());
+    return Candidates.back();
+  }
+
+  void NoteCandidates(Sema &S, SourceLocation Loc);
+
+  void NoteCandidates(Sema &S, SourceLocation Loc) const {
+    const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
+  }
+};
+
+} // end namespace clang
 
 #endif

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jul 19 17:34:32 2013
@@ -548,13 +548,13 @@ AmbiguousConversionSequence::copyFrom(co
 }
 
 namespace {
-  // Structure used by OverloadCandidate::DeductionFailureInfo to store
+  // Structure used by DeductionFailureInfo to store
   // template argument information.
   struct DFIArguments {
     TemplateArgument FirstArg;
     TemplateArgument SecondArg;
   };
-  // Structure used by OverloadCandidate::DeductionFailureInfo to store
+  // Structure used by DeductionFailureInfo to store
   // template parameter and template argument information.
   struct DFIParamWithArguments : DFIArguments {
     TemplateParameter Param;
@@ -563,11 +563,10 @@ namespace {
 
 /// \brief Convert from Sema's representation of template deduction information
 /// to the form used in overload-candidate information.
-OverloadCandidate::DeductionFailureInfo
-static MakeDeductionFailureInfo(ASTContext &Context,
-                                Sema::TemplateDeductionResult TDK,
-                                TemplateDeductionInfo &Info) {
-  OverloadCandidate::DeductionFailureInfo Result;
+DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
+                                              Sema::TemplateDeductionResult TDK,
+                                              TemplateDeductionInfo &Info) {
+  DeductionFailureInfo Result;
   Result.Result = static_cast<unsigned>(TDK);
   Result.HasDiagnostic = false;
   Result.Data = 0;
@@ -625,7 +624,7 @@ static MakeDeductionFailureInfo(ASTConte
   return Result;
 }
 
-void OverloadCandidate::DeductionFailureInfo::Destroy() {
+void DeductionFailureInfo::Destroy() {
   switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
   case Sema::TDK_Success:
   case Sema::TDK_Invalid:
@@ -659,15 +658,13 @@ void OverloadCandidate::DeductionFailure
   }
 }
 
-PartialDiagnosticAt *
-OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() {
+PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
   if (HasDiagnostic)
     return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
   return 0;
 }
 
-TemplateParameter
-OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
+TemplateParameter DeductionFailureInfo::getTemplateParameter() {
   switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
   case Sema::TDK_Success:
   case Sema::TDK_Invalid:
@@ -695,8 +692,7 @@ OverloadCandidate::DeductionFailureInfo:
   return TemplateParameter();
 }
 
-TemplateArgumentList *
-OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
+TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
   switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
   case Sema::TDK_Success:
   case Sema::TDK_Invalid:
@@ -722,7 +718,7 @@ OverloadCandidate::DeductionFailureInfo:
   return 0;
 }
 
-const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
+const TemplateArgument *DeductionFailureInfo::getFirstArg() {
   switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
   case Sema::TDK_Success:
   case Sema::TDK_Invalid:
@@ -748,8 +744,7 @@ const TemplateArgument *OverloadCandidat
   return 0;
 }
 
-const TemplateArgument *
-OverloadCandidate::DeductionFailureInfo::getSecondArg() {
+const TemplateArgument *DeductionFailureInfo::getSecondArg() {
   switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
   case Sema::TDK_Success:
   case Sema::TDK_Invalid:
@@ -775,8 +770,7 @@ OverloadCandidate::DeductionFailureInfo:
   return 0;
 }
 
-Expr *
-OverloadCandidate::DeductionFailureInfo::getExpr() {
+Expr *DeductionFailureInfo::getExpr() {
   if (static_cast<Sema::TemplateDeductionResult>(Result) ==
         Sema::TDK_FailedOverloadResolution)
     return static_cast<Expr*>(Data);
@@ -8128,7 +8122,7 @@ OverloadCandidateKind ClassifyOverloadCa
   return isTemplate ? oc_function_template : oc_function;
 }
 
-void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
+void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
   const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
   if (!Ctor) return;
 
@@ -8414,30 +8408,52 @@ void DiagnoseBadConversion(Sema &S, Over
   MaybeEmitInheritedConstructorNote(S, Fn);
 }
 
-void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
-                           unsigned NumFormalArgs) {
-  // TODO: treat calls to a missing default constructor as a special case
-
+/// Additional arity mismatch diagnosis specific to a function overload
+/// candidates. This is not covered by the more general DiagnoseArityMismatch()
+/// over a candidate in any candidate set.
+bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
+                        unsigned NumArgs) {
   FunctionDecl *Fn = Cand->Function;
-  const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
-
   unsigned MinParams = Fn->getMinRequiredArguments();
 
   // With invalid overloaded operators, it's possible that we think we
-  // have an arity mismatch when it fact it looks like we have the
+  // have an arity mismatch when in fact it looks like we have the
   // right number of arguments, because only overloaded operators have
   // the weird behavior of overloading member and non-member functions.
   // Just don't report anything.
   if (Fn->isInvalidDecl() && 
       Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
-    return;
+    return true;
 
-  // at least / at most / exactly
-  unsigned mode, modeCount;
-  if (NumFormalArgs < MinParams) {
+  if (NumArgs < MinParams) {
     assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
            (Cand->FailureKind == ovl_fail_bad_deduction &&
             Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
+  } else {
+    assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
+           (Cand->FailureKind == ovl_fail_bad_deduction &&
+            Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
+  }
+
+  return false;
+}
+
+/// General arity mismatch diagnosis over a candidate in a candidate set.
+void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
+  assert(isa<FunctionDecl>(D) &&
+      "The templated declaration should at least be a function"
+      " when diagnosing bad template argument deduction due to too many"
+      " or too few arguments");
+  
+  FunctionDecl *Fn = cast<FunctionDecl>(D);
+  
+  // TODO: treat calls to a missing default constructor as a special case
+  const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+  unsigned MinParams = Fn->getMinRequiredArguments();
+
+  // at least / at most / exactly
+  unsigned mode, modeCount;
+  if (NumFormalArgs < MinParams) {
     if (MinParams != FnTy->getNumArgs() ||
         FnTy->isVariadic() || FnTy->isTemplateVariadic())
       mode = 0; // "at least"
@@ -8445,9 +8461,6 @@ void DiagnoseArityMismatch(Sema &S, Over
       mode = 2; // "exactly"
     modeCount = MinParams;
   } else {
-    assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
-           (Cand->FailureKind == ovl_fail_bad_deduction &&
-            Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
     if (MinParams != FnTy->getNumArgs())
       mode = 1; // "at most"
     else
@@ -8469,25 +8482,42 @@ void DiagnoseArityMismatch(Sema &S, Over
   MaybeEmitInheritedConstructorNote(S, Fn);
 }
 
+/// Arity mismatch diagnosis specific to a function overload candidate.
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+                           unsigned NumFormalArgs) {
+  if (!CheckArityMismatch(S, Cand, NumFormalArgs))
+    DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
+}
+
+TemplateDecl *getDescribedTemplate(Decl *Templated) {
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
+    return FD->getDescribedFunctionTemplate();
+  else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
+    return RD->getDescribedClassTemplate();
+
+  llvm_unreachable("Unsupported: Getting the described template declaration"
+                   " for bad deduction diagnosis");
+}
+
 /// Diagnose a failed template-argument deduction.
-void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+void DiagnoseBadDeduction(Sema &S, Decl *Templated,
+                          DeductionFailureInfo &DeductionFailure,
                           unsigned NumArgs) {
-  FunctionDecl *Fn = Cand->Function; // pattern
-
-  TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
+  TemplateParameter Param = DeductionFailure.getTemplateParameter();
   NamedDecl *ParamD;
   (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
   (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
   (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
-  switch (Cand->DeductionFailure.Result) {
+  switch (DeductionFailure.Result) {
   case Sema::TDK_Success:
     llvm_unreachable("TDK_success while diagnosing bad deduction");
 
   case Sema::TDK_Incomplete: {
     assert(ParamD && "no parameter found for incomplete deduction result");
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
-      << ParamD->getDeclName();
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_incomplete_deduction)
+        << ParamD->getDeclName();
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
   }
 
@@ -8495,7 +8525,7 @@ void DiagnoseBadDeduction(Sema &S, Overl
     assert(ParamD && "no parameter found for bad qualifiers deduction result");
     TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
 
-    QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
+    QualType Param = DeductionFailure.getFirstArg()->getAsType();
 
     // Param will have been canonicalized, but it should just be a
     // qualified version of ParamD, so move the qualifiers to that.
@@ -8508,11 +8538,11 @@ void DiagnoseBadDeduction(Sema &S, Overl
     // about that.  It also doesn't matter as much, because it won't
     // have any template parameters in it (because deduction isn't
     // done on dependent types).
-    QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
+    QualType Arg = DeductionFailure.getSecondArg()->getAsType();
 
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
-      << ParamD->getDeclName() << Arg << NonCanonParam;
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified)
+        << ParamD->getDeclName() << Arg << NonCanonParam;
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
   }
 
@@ -8527,20 +8557,20 @@ void DiagnoseBadDeduction(Sema &S, Overl
       which = 2;
     }
 
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
-      << which << ParamD->getDeclName()
-      << *Cand->DeductionFailure.getFirstArg()
-      << *Cand->DeductionFailure.getSecondArg();
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_inconsistent_deduction)
+        << which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
+        << *DeductionFailure.getSecondArg();
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
   }
 
   case Sema::TDK_InvalidExplicitArguments:
     assert(ParamD && "no parameter found for invalid explicit arguments");
     if (ParamD->getDeclName())
-      S.Diag(Fn->getLocation(),
+      S.Diag(Templated->getLocation(),
              diag::note_ovl_candidate_explicit_arg_mismatch_named)
-        << ParamD->getDeclName();
+          << ParamD->getDeclName();
     else {
       int index = 0;
       if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
@@ -8550,35 +8580,36 @@ void DiagnoseBadDeduction(Sema &S, Overl
         index = NTTP->getIndex();
       else
         index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
-      S.Diag(Fn->getLocation(),
+      S.Diag(Templated->getLocation(),
              diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
-        << (index + 1);
+          << (index + 1);
     }
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
 
   case Sema::TDK_TooManyArguments:
   case Sema::TDK_TooFewArguments:
-    DiagnoseArityMismatch(S, Cand, NumArgs);
+    DiagnoseArityMismatch(S, Templated, NumArgs);
     return;
 
   case Sema::TDK_InstantiationDepth:
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_instantiation_depth);
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
 
   case Sema::TDK_SubstitutionFailure: {
     // Format the template argument list into the argument string.
     SmallString<128> TemplateArgString;
     if (TemplateArgumentList *Args =
-          Cand->DeductionFailure.getTemplateArgumentList()) {
+            DeductionFailure.getTemplateArgumentList()) {
       TemplateArgString = " ";
       TemplateArgString += S.getTemplateArgumentBindingsText(
-          Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args);
+          getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
     }
 
     // If this candidate was disabled by enable_if, say so.
-    PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic();
+    PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic();
     if (PDiag && PDiag->second.getDiagID() ==
           diag::err_typename_nested_not_found_enable_if) {
       // FIXME: Use the source range of the condition, and the fully-qualified
@@ -8599,25 +8630,25 @@ void DiagnoseBadDeduction(Sema &S, Overl
       PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
     }
 
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
-      << TemplateArgString << SFINAEArgString << R;
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_substitution_failure)
+        << TemplateArgString << SFINAEArgString << R;
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
   }
 
   case Sema::TDK_FailedOverloadResolution: {
-    OverloadExpr::FindResult R =
-        OverloadExpr::find(Cand->DeductionFailure.getExpr());
-    S.Diag(Fn->getLocation(),
+    OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr());
+    S.Diag(Templated->getLocation(),
            diag::note_ovl_candidate_failed_overload_resolution)
-      << R.Expression->getName();
+        << R.Expression->getName();
     return;
   }
 
   case Sema::TDK_NonDeducedMismatch: {
     // FIXME: Provide a source location to indicate what we couldn't match.
-    TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg();
-    TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg();
+    TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
+    TemplateArgument SecondTA = *DeductionFailure.getSecondArg();
     if (FirstTA.getKind() == TemplateArgument::Template &&
         SecondTA.getKind() == TemplateArgument::Template) {
       TemplateName FirstTN = FirstTA.getAsTemplate();
@@ -8632,26 +8663,38 @@ void DiagnoseBadDeduction(Sema &S, Overl
           // 2) The diagnostic printer only attempts to find a better
           //    name for types, not decls.
           // Ideally, this should folded into the diagnostic printer.
-          S.Diag(Fn->getLocation(),
+          S.Diag(Templated->getLocation(),
                  diag::note_ovl_candidate_non_deduced_mismatch_qualified)
               << FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl();
           return;
         }
       }
     }
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch)
-      << FirstTA << SecondTA;
+    S.Diag(Templated->getLocation(),
+           diag::note_ovl_candidate_non_deduced_mismatch)
+        << FirstTA << SecondTA;
     return;
   }
   // TODO: diagnose these individually, then kill off
   // note_ovl_candidate_bad_deduction, which is uselessly vague.
   case Sema::TDK_MiscellaneousDeductionFailure:
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
-    MaybeEmitInheritedConstructorNote(S, Fn);
+    S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
+    MaybeEmitInheritedConstructorNote(S, Templated);
     return;
   }
 }
 
+/// Diagnose a failed template-argument deduction, for function calls.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
+  unsigned TDK = Cand->DeductionFailure.Result;
+  if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
+    if (CheckArityMismatch(S, Cand, NumArgs))
+      return;
+  }
+  DiagnoseBadDeduction(S, Cand->Function, // pattern
+                       Cand->DeductionFailure, NumArgs);
+}
+
 /// CUDA: diagnose an invalid call across targets.
 void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
   FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
@@ -8799,7 +8842,7 @@ void NoteAmbiguousUserConversions(Sema &
   }
 }
 
-SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
   if (Cand->Function)
     return Cand->Function->getLocation();
   if (Cand->IsSurrogate)
@@ -8807,8 +8850,7 @@ SourceLocation GetLocationForCandidate(c
   return SourceLocation();
 }
 
-static unsigned
-RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) {
+static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
   switch ((Sema::TemplateDeductionResult)DFI.Result) {
   case Sema::TDK_Success:
     llvm_unreachable("TDK_success while diagnosing bad deduction");
@@ -9101,6 +9143,108 @@ void OverloadCandidateSet::NoteCandidate
     S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
 }
 
+static SourceLocation
+GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
+  return Cand->Specialization ? Cand->Specialization->getLocation()
+                              : SourceLocation();
+}
+
+struct CompareTemplateSpecCandidatesForDisplay {
+  Sema &S;
+  CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {}
+
+  bool operator()(const TemplateSpecCandidate *L,
+                  const TemplateSpecCandidate *R) {
+    // Fast-path this check.
+    if (L == R)
+      return false;
+
+    // Assuming that both candidates are not matches...
+
+    // Sort by the ranking of deduction failures.
+    if (L->DeductionFailure.Result != R->DeductionFailure.Result)
+      return RankDeductionFailure(L->DeductionFailure) <
+             RankDeductionFailure(R->DeductionFailure);
+
+    // Sort everything else by location.
+    SourceLocation LLoc = GetLocationForCandidate(L);
+    SourceLocation RLoc = GetLocationForCandidate(R);
+
+    // Put candidates without locations (e.g. builtins) at the end.
+    if (LLoc.isInvalid())
+      return false;
+    if (RLoc.isInvalid())
+      return true;
+
+    return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
+  }
+};
+
+/// Diagnose a template argument deduction failure.
+/// We are treating these failures as overload failures due to bad
+/// deductions.
+void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) {
+  DiagnoseBadDeduction(S, Specialization, // pattern
+                       DeductionFailure, /*NumArgs=*/0);
+}
+
+void TemplateSpecCandidateSet::destroyCandidates() {
+  for (iterator i = begin(), e = end(); i != e; ++i) {
+    i->DeductionFailure.Destroy();
+  }
+}
+
+void TemplateSpecCandidateSet::clear() {
+  destroyCandidates();
+  Candidates.clear();
+}
+
+/// NoteCandidates - When no template specialization match is found, prints
+/// diagnostic messages containing the non-matching specializations that form
+/// the candidate set.
+/// This is analoguous to OverloadCandidateSet::NoteCandidates() with
+/// OCD == OCD_AllCandidates and Cand->Viable == false.
+void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
+  // Sort the candidates by position (assuming no candidate is a match).
+  // Sorting directly would be prohibitive, so we make a set of pointers
+  // and sort those.
+  SmallVector<TemplateSpecCandidate *, 32> Cands;
+  Cands.reserve(size());
+  for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
+    if (Cand->Specialization)
+      Cands.push_back(Cand);
+    // Otherwise, this is a non matching builtin candidate.  We do not,
+    // in general, want to list every possible builtin candidate.
+  }
+
+  std::sort(Cands.begin(), Cands.end(),
+            CompareTemplateSpecCandidatesForDisplay(S));
+
+  // FIXME: Perhaps rename OverloadsShown and getShowOverloads()
+  // for generalization purposes (?).
+  const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
+
+  SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E;
+  unsigned CandsShown = 0;
+  for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+    TemplateSpecCandidate *Cand = *I;
+
+    // Set an arbitrary limit on the number of candidates we'll spam
+    // the user with.  FIXME: This limit should depend on details of the
+    // candidate list.
+    if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
+      break;
+    ++CandsShown;
+
+    assert(Cand->Specialization &&
+           "Non-matching built-in candidates are not added to Cands.");
+    Cand->NoteDeductionFailure(S);
+  }
+
+  if (I != E)
+    S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I);
+}
+
 // [PossiblyAFunctionType]  -->   [Return]
 // NonFunctionType --> NonFunctionType
 // R (A) --> R(A)
@@ -9143,18 +9287,19 @@ class AddressOfFunctionResolver
   OverloadExpr *OvlExpr;
   TemplateArgumentListInfo OvlExplicitTemplateArgs;
   SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+  TemplateSpecCandidateSet FailedCandidates;
 
 public:
-  AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, 
-                            const QualType& TargetType, bool Complain)
-    : S(S), SourceExpr(SourceExpr), TargetType(TargetType), 
-      Complain(Complain), Context(S.getASTContext()), 
-      TargetTypeIsNonStaticMemberFunction(
-                                    !!TargetType->getAs<MemberPointerType>()),
-      FoundNonTemplateFunction(false),
-      OvlExprInfo(OverloadExpr::find(SourceExpr)),
-      OvlExpr(OvlExprInfo.Expression)
-  {
+  AddressOfFunctionResolver(Sema &S, Expr *SourceExpr,
+                            const QualType &TargetType, bool Complain)
+      : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
+        Complain(Complain), Context(S.getASTContext()),
+        TargetTypeIsNonStaticMemberFunction(
+            !!TargetType->getAs<MemberPointerType>()),
+        FoundNonTemplateFunction(false),
+        OvlExprInfo(OverloadExpr::find(SourceExpr)),
+        OvlExpr(OvlExprInfo.Expression),
+        FailedCandidates(OvlExpr->getNameLoc()) {
     ExtractUnqualifiedFunctionTypeFromTargetType();
     
     if (!TargetFunctionType->isFunctionType()) {        
@@ -9232,13 +9377,16 @@ private:
     //   function template specialization, which is added to the set of
     //   overloaded functions considered.
     FunctionDecl *Specialization = 0;
-    TemplateDeductionInfo Info(OvlExpr->getNameLoc());
+    TemplateDeductionInfo Info(FailedCandidates.getLocation());
     if (Sema::TemplateDeductionResult Result
           = S.DeduceTemplateArguments(FunctionTemplate, 
                                       &OvlExplicitTemplateArgs,
                                       TargetFunctionType, Specialization, 
                                       Info, /*InOverloadResolution=*/true)) {
-      // FIXME: make a note of the failed deduction for diagnostics.
+      // Make a note of the failed deduction for diagnostics.
+      FailedCandidates.addCandidate()
+          .set(FunctionTemplate->getTemplatedDecl(),
+               MakeDeductionFailureInfo(Context, Result, Info));
       (void)Result;
       return false;
     } 
@@ -9343,15 +9491,15 @@ private:
     for (unsigned I = 0, E = Matches.size(); I != E; ++I)
       MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
 
-    UnresolvedSetIterator Result =
-      S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
-                           TPOC_Other, 0, SourceExpr->getLocStart(),
-                           S.PDiag(),
-                           S.PDiag(diag::err_addr_ovl_ambiguous)
-                             << Matches[0].second->getDeclName(),
-                           S.PDiag(diag::note_ovl_candidate)
-                             << (unsigned) oc_function_template,
-                           Complain, TargetFunctionType);
+    // TODO: It looks like FailedCandidates does not serve much purpose
+    // here, since the no_viable diagnostic has index 0.
+    UnresolvedSetIterator Result = S.getMostSpecialized(
+        MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, TPOC_Other, 0,
+        SourceExpr->getLocStart(), S.PDiag(),
+        S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
+                                                     .second->getDeclName(),
+        S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template,
+        Complain, TargetFunctionType);
 
     if (Result != MatchesCopy.end()) {
       // Make it the first and only element
@@ -9380,6 +9528,7 @@ public:
     S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
         << OvlExpr->getName() << TargetFunctionType
         << OvlExpr->getSourceRange();
+    FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
     S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
   } 
   
@@ -9496,6 +9645,7 @@ Sema::ResolveSingleFunctionTemplateSpeci
 
   TemplateArgumentListInfo ExplicitTemplateArgs;
   ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+  TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
 
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
@@ -9518,12 +9668,16 @@ Sema::ResolveSingleFunctionTemplateSpeci
     //   function template specialization, which is added to the set of
     //   overloaded functions considered.
     FunctionDecl *Specialization = 0;
-    TemplateDeductionInfo Info(ovl->getNameLoc());
+    TemplateDeductionInfo Info(FailedCandidates.getLocation());
     if (TemplateDeductionResult Result
           = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
                                     Specialization, Info,
                                     /*InOverloadResolution=*/true)) {
-      // FIXME: make a note of the failed deduction for diagnostics.
+      // Make a note of the failed deduction for diagnostics.
+      // TODO: Actually use the failed-deduction info?
+      FailedCandidates.addCandidate()
+          .set(FunctionTemplate->getTemplatedDecl(),
+               MakeDeductionFailureInfo(Context, Result, Info));
       (void)Result;
       continue;
     }

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Jul 19 17:34:32 2013
@@ -5925,13 +5925,13 @@ Sema::CheckDependentFunctionTemplateSpec
 ///
 /// \param Previous the set of declarations that may be specialized by
 /// this function specialization.
-bool
-Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
-                                 TemplateArgumentListInfo *ExplicitTemplateArgs,
-                                          LookupResult &Previous) {
+bool Sema::CheckFunctionTemplateSpecialization(
+    FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
+    LookupResult &Previous) {
   // The set of function template specializations that could match this
   // explicit function template specialization.
   UnresolvedSet<8> Candidates;
+  TemplateSpecCandidateSet FailedCandidates(FD->getLocation());
 
   DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
   for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
@@ -5969,13 +5969,16 @@ Sema::CheckFunctionTemplateSpecializatio
       // Perform template argument deduction to determine whether we may be
       // specializing this template.
       // FIXME: It is somewhat wasteful to build
-      TemplateDeductionInfo Info(FD->getLocation());
+      TemplateDeductionInfo Info(FailedCandidates.getLocation());
       FunctionDecl *Specialization = 0;
       if (TemplateDeductionResult TDK
             = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT,
                                       Specialization, Info)) {
-        // FIXME: Template argument deduction failed; record why it failed, so
+        // Template argument deduction failed; record why it failed, so
         // that we can provide nifty diagnostics.
+        FailedCandidates.addCandidate()
+            .set(FunTmpl->getTemplatedDecl(),
+                 MakeDeductionFailureInfo(Context, TDK, Info));
         (void)TDK;
         continue;
       }
@@ -5986,14 +5989,14 @@ Sema::CheckFunctionTemplateSpecializatio
   }
 
   // Find the most specialized function template.
-  UnresolvedSetIterator Result
-    = getMostSpecialized(Candidates.begin(), Candidates.end(),
-                         TPOC_Other, 0, FD->getLocation(),
-                  PDiag(diag::err_function_template_spec_no_match)
-                    << FD->getDeclName(),
-                  PDiag(diag::err_function_template_spec_ambiguous)
-                    << FD->getDeclName() << (ExplicitTemplateArgs != 0),
-                  PDiag(diag::note_function_template_spec_matched));
+  UnresolvedSetIterator Result = getMostSpecialized(
+      Candidates.begin(), Candidates.end(), FailedCandidates, TPOC_Other, 0,
+      FD->getLocation(),
+      PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(),
+      PDiag(diag::err_function_template_spec_ambiguous)
+          << FD->getDeclName() << (ExplicitTemplateArgs != 0),
+      PDiag(diag::note_function_template_spec_matched));
+
   if (Result == Candidates.end())
     return true;
 
@@ -6812,6 +6815,7 @@ DeclResult Sema::ActOnExplicitInstantiat
   //  instantiated from the member definition associated with its class
   //  template.
   UnresolvedSet<8> Matches;
+  TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc());
   for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end();
        P != PEnd; ++P) {
     NamedDecl *Prev = *P;
@@ -6831,13 +6835,16 @@ DeclResult Sema::ActOnExplicitInstantiat
     if (!FunTmpl)
       continue;
 
-    TemplateDeductionInfo Info(D.getIdentifierLoc());
+    TemplateDeductionInfo Info(FailedCandidates.getLocation());
     FunctionDecl *Specialization = 0;
     if (TemplateDeductionResult TDK
           = DeduceTemplateArguments(FunTmpl,
                                (HasExplicitTemplateArgs ? &TemplateArgs : 0),
                                     R, Specialization, Info)) {
-      // FIXME: Keep track of almost-matches?
+      // Keep track of almost-matches.
+      FailedCandidates.addCandidate()
+          .set(FunTmpl->getTemplatedDecl(),
+               MakeDeductionFailureInfo(Context, TDK, Info));
       (void)TDK;
       continue;
     }
@@ -6846,12 +6853,12 @@ DeclResult Sema::ActOnExplicitInstantiat
   }
 
   // Find the most specialized function template specialization.
-  UnresolvedSetIterator Result
-    = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0,
-                         D.getIdentifierLoc(),
-                     PDiag(diag::err_explicit_instantiation_not_known) << Name,
-                     PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
-                         PDiag(diag::note_explicit_instantiation_candidate));
+  UnresolvedSetIterator Result = getMostSpecialized(
+      Matches.begin(), Matches.end(), FailedCandidates, TPOC_Other, 0,
+      D.getIdentifierLoc(),
+      PDiag(diag::err_explicit_instantiation_not_known) << Name,
+      PDiag(diag::err_explicit_instantiation_ambiguous) << Name,
+      PDiag(diag::note_explicit_instantiation_candidate));
 
   if (Result == Matches.end())
     return true;

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Jul 19 17:34:32 2013
@@ -4148,23 +4148,18 @@ static bool isSameTemplate(TemplateDecl
 ///
 /// \returns the most specialized function template specialization, if
 /// found. Otherwise, returns SpecEnd.
-///
-/// \todo FIXME: Consider passing in the "also-ran" candidates that failed
-/// template argument deduction.
-UnresolvedSetIterator
-Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin,
-                         UnresolvedSetIterator SpecEnd,
-                         TemplatePartialOrderingContext TPOC,
-                         unsigned NumCallArguments,
-                         SourceLocation Loc,
-                         const PartialDiagnostic &NoneDiag,
-                         const PartialDiagnostic &AmbigDiag,
-                         const PartialDiagnostic &CandidateDiag,
-                         bool Complain,
-                         QualType TargetType) {
+UnresolvedSetIterator Sema::getMostSpecialized(
+    UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd,
+    TemplateSpecCandidateSet &FailedCandidates,
+    TemplatePartialOrderingContext TPOC, unsigned NumCallArguments,
+    SourceLocation Loc, const PartialDiagnostic &NoneDiag,
+    const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag,
+    bool Complain, QualType TargetType) {
   if (SpecBegin == SpecEnd) {
-    if (Complain)
+    if (Complain) {
       Diag(Loc, NoneDiag);
+      FailedCandidates.NoteCandidates(*this, Loc);
+    }
     return SpecEnd;
   }
 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Jul 19 17:34:32 2013
@@ -2252,15 +2252,18 @@ Sema::InstantiateClassTemplateSpecializa
   SmallVector<MatchResult, 4> Matched;
   SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
   Template->getPartialSpecializations(PartialSpecs);
+  TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation);
   for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) {
     ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I];
-    TemplateDeductionInfo Info(PointOfInstantiation);
+    TemplateDeductionInfo Info(FailedCandidates.getLocation());
     if (TemplateDeductionResult Result
           = DeduceTemplateArguments(Partial,
                                     ClassTemplateSpec->getTemplateArgs(),
                                     Info)) {
-      // FIXME: Store the failed-deduction information for use in
-      // diagnostics, later.
+      // Store the failed-deduction information for use in diagnostics, later.
+      // TODO: Actually use the failed-deduction info?
+      FailedCandidates.addCandidate()
+          .set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
       (void)Result;
     } else {
       Matched.push_back(PartialSpecMatchResult());

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp Fri Jul 19 17:34:32 2013
@@ -72,7 +72,8 @@ template <typename T> constexpr T ft(T t
 template <typename T> T gt(T t) { return t; }
 struct S {
   template<typename T> constexpr T f(); // expected-warning {{C++1y}}
-  template<typename T> T g() const;
+  template <typename T>
+  T g() const; // expected-note {{candidate template ignored: could not match 'T () const' against 'char ()'}}
 };
 
 // explicit specialization can differ in constepxr

Modified: cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.const/p3-0x.cpp Fri Jul 19 17:34:32 2013
@@ -93,7 +93,7 @@ void c() {
     break;
   }
 }
-template<bool B> int f() { return B; }
+template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}}
 template int f<&S::operator int>(); // expected-error {{does not refer to a function template}}
 template int f<(bool)&S::operator int>();
 

Modified: cfe/trunk/test/CXX/over/over.over/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.over/p2.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p2.cpp (original)
+++ cfe/trunk/test/CXX/over/over.over/p2.cpp Fri Jul 19 17:34:32 2013
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-template<typename T> T f0(T, T); //expected-note{{candidate}}
+template <typename T>
+T f0(T, T); // expected-note{{candidate}} expected-note{{candidate function}}
 
 void test_f0() {
   int (*f0a)(int, int) = f0;

Modified: cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp (original)
+++ cfe/trunk/test/SemaCXX/addr-of-overloaded-function-casting.cpp Fri Jul 19 17:34:32 2013
@@ -4,8 +4,12 @@ void g();
 void f(); // expected-note 9{{candidate function}}
 void f(int); // expected-note 9{{candidate function}}
 
-template<class T> void t(T); // expected-note 6{{candidate function}}
-template<class T> void t(T*); // expected-note 6{{candidate function}}
+template <class T>
+void t(T); // expected-note 6{{candidate function}} \
+           // expected-note 3{{candidate template ignored: could not match 'void' against 'int'}}
+template <class T>
+void t(T *); // expected-note 6{{candidate function}} \
+             // expected-note 3{{candidate template ignored: could not match 'void' against 'int'}}
 
 template<class T> void u(T);
 

Modified: cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx1y-deduced-return-type.cpp Fri Jul 19 17:34:32 2013
@@ -112,7 +112,8 @@ namespace Templates {
   int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}}
   template<typename T> auto fwd_decl() { return 0; }
   int f = fwd_decl<int>();
-  template<typename T> auto fwd_decl();
+  template <typename T>
+  auto fwd_decl(); // expected-note {{candidate template ignored: could not match 'auto ()' against 'int ()'}}
   int g = fwd_decl<char>();
 
   auto (*p)() = f1; // expected-error {{incompatible initializer}}
@@ -126,7 +127,8 @@ namespace Templates {
   extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}}
   int k2 = fwd_decl<char>();
 
-  template<typename T> auto instantiate() { T::error; } // expected-error {{has no members}}
+  template <typename T> auto instantiate() { T::error; } // expected-error {{has no members}} \
+    // expected-note {{candidate template ignored: could not match 'auto ()' against 'void ()'}}
   extern template auto instantiate<int>(); // ok
   int k = instantiate<int>(); // expected-note {{in instantiation of}}
   template<> auto instantiate<char>() {} // ok
@@ -157,7 +159,8 @@ namespace Templates {
   double &mem_check4 = take_fn<double>(Outer<double>::arg_multi);
 
   namespace Deduce1 {
-    template<typename T> auto f() { return 0; } // expected-note {{candidate}}
+  template <typename T> auto f() { return 0; } // expected-note {{candidate}} \
+                                               // expected-note {{candidate function has different return type ('int' expected but has 'auto')}}
     template<typename T> void g(T(*)()); // expected-note 2{{candidate}}
     void h() {
       auto p = f<int>;
@@ -170,7 +173,8 @@ namespace Templates {
   }
 
   namespace Deduce2 {
-    template<typename T> auto f(int) { return 0; } // expected-note {{candidate}}
+  template <typename T> auto f(int) { return 0; } // expected-note {{candidate}} \
+    // expected-note {{candidate function has different return type ('int' expected but has 'auto')}}
     template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}}
     void h() {
       auto p = f<int>;
@@ -322,7 +326,8 @@ namespace Redecl {
   int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
   decltype(auto) f(); // expected-error {{cannot be overloaded}}
 
-  template<typename T> auto g(T t) { return t; } // expected-note {{candidate}}
+  template <typename T> auto g(T t) { return t; } // expected-note {{candidate}} \
+                                                  // expected-note {{candidate function [with T = int]}}
   template auto g(int);
   template char g(char); // expected-error {{does not refer to a function}}
   template<> auto g(double);

Modified: cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-nsconsumed-errors.mm Fri Jul 19 17:34:32 2013
@@ -29,11 +29,13 @@ void releaser(__attribute__((ns_consumed
 releaser_t r2 = releaser; // no-warning
 
 template <typename T>
-void templateFunction(T) {} // expected-note {{candidate function}}
+void templateFunction(T) { } // expected-note {{candidate function}} \
+                             // expected-note {{candidate template ignored: could not match 'void (__strong id)' against 'void (id)'}} \
+                             // expected-note {{candidate template ignored: failed template argument deduction}}
 releaser_t r3 = templateFunction<id>; // expected-error {{address of overloaded function 'templateFunction' does not match required type 'void (id)'}}
 
 template <typename T>
-void templateReleaser(__attribute__((ns_consumed)) T) {}
+void templateReleaser(__attribute__((ns_consumed)) T) { } // expected-note 2{{candidate template ignored: failed template argument deduction}}
 releaser_t r4 = templateReleaser<id>; // no-warning
 
 

Modified: cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp (original)
+++ cfe/trunk/test/SemaTemplate/explicit-instantiation.cpp Fri Jul 19 17:34:32 2013
@@ -15,9 +15,9 @@ struct X0 {
     return x + 1;  // expected-error{{invalid operands}}
   } 
   T* f0(T*, T*) { return T(); } // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
-  
-  template<typename U>
-  T f0(T, U) { return T(); }
+
+  template <typename U> T f0(T, U) { return T(); } // expected-note {{candidate template ignored: could not match 'int (int, U)' against 'int (int) const'}} \
+                                                   // expected-note {{candidate template ignored: could not match 'int' against 'int *'}}
 };
 
 template<typename T>
@@ -59,13 +59,14 @@ template int *X2::f1(int *); // okay
 
 template void X2::f2(int *, int *); // expected-error{{ambiguous}}
 
-
-template<typename T> void print_type() { }
+template <typename T>
+void print_type() {} // expected-note {{candidate template ignored: could not match 'void ()' against 'void (float *)'}}
 
 template void print_type<int>();
 template void print_type<float>();
 
-template<typename T> void print_type(T*) { }
+template <typename T>
+void print_type(T *) {} // expected-note {{candidate template ignored: could not match 'void (int *)' against 'void (float *)'}}
 
 template void print_type(int*);
 template void print_type<int>(float*); // expected-error{{does not refer}}
@@ -94,7 +95,7 @@ namespace PR7622 {
 
   template<typename,typename>
   struct basic_streambuf{friend bob<>()}; // expected-error{{unknown type name 'bob'}} \
-  // expected-error{{expected member name or ';' after declaration specifiers}}
+                                          // expected-error{{expected member name or ';' after declaration specifiers}}
   template struct basic_streambuf<int>;
 }
 

Modified: cfe/trunk/test/SemaTemplate/function-template-specialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/function-template-specialization.cpp?rev=186727&r1=186726&r2=186727&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/function-template-specialization.cpp (original)
+++ cfe/trunk/test/SemaTemplate/function-template-specialization.cpp Fri Jul 19 17:34:32 2013
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-template<int N> void f0(int (&array)[N]);
+template <int N>
+void f0(int (&array)[N]); // expected-note {{candidate template ignored: could not match 'int' against 'char'}}
 
 // Simple function template specialization (using overloading)
 template<> void f0(int (&array)[1]);





More information about the cfe-commits mailing list