]> granicus.if.org Git - clang/commitdiff
When printing an overload candidate that failed due to SFINAE, print a
authorDouglas Gregor <dgregor@apple.com>
Sat, 8 May 2010 20:07:26 +0000 (20:07 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 8 May 2010 20:07:26 +0000 (20:07 +0000)
specific message that includes the template arguments, e.g.,

test/SemaTemplate/overload-candidates.cpp:27:20: note: candidate template
      ignored: substitution failure [with T = int *]
  typename T::type get_type(const T&); // expected-note{{candidate ...
                   ^

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
lib/Sema/SemaOverload.h
lib/Sema/SemaTemplateDeduction.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp
test/SemaTemplate/overload-candidates.cpp

index 235ac86a22c2028146c6b8e39baf2c43c07b7387..95dce63c05535f268af2833268adfcd31bdfeac9 100644 (file)
@@ -1069,7 +1069,12 @@ def note_ovl_candidate_explicit_arg_mismatch_named : Note<
 def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
     "candidate template ignored: invalid explicitly-specified argument "
     "for %ordinal0 template parameter">;
-
+def note_ovl_candidate_instantiation_depth : Note<
+    "candidate template ignored: substitution exceeded maximum template "
+    "instantiation depth">;
+def note_ovl_candidate_substitution_failure : Note<
+    "candidate template ignored: substitution failure %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 f7382361333112573d33a9f7ae083191a57763f7..b86719e15b97bf973eb64c4a9b06c945bf0668b0 100644 (file)
@@ -289,7 +289,7 @@ namespace {
 /// to the form used in overload-candidate information.
 OverloadCandidate::DeductionFailureInfo
 static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
-                                const Sema::TemplateDeductionInfo &Info) {
+                                Sema::TemplateDeductionInfo &Info) {
   OverloadCandidate::DeductionFailureInfo Result;
   Result.Result = static_cast<unsigned>(TDK);
   Result.Data = 0;
@@ -316,6 +316,9 @@ static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
   }
       
   case Sema::TDK_SubstitutionFailure:
+    Result.Data = Info.take();
+    break;
+      
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
     break;  
@@ -339,9 +342,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
     delete static_cast<DFIParamWithArguments*>(Data);
     Data = 0;
     break;
+
+  case Sema::TDK_SubstitutionFailure:
+    // FIXME: Destroy the template arugment list?
+    Data = 0;
+    break;
       
   // Unhandled
-  case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
     break;
@@ -355,6 +362,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
   case Sema::TDK_InstantiationDepth:
   case Sema::TDK_TooManyArguments:
   case Sema::TDK_TooFewArguments:
+  case Sema::TDK_SubstitutionFailure:
     return TemplateParameter();
     
   case Sema::TDK_Incomplete:
@@ -366,7 +374,6 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
     return static_cast<DFIParamWithArguments*>(Data)->Param;
       
   // Unhandled
-  case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
     break;
@@ -374,7 +381,32 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
   
   return TemplateParameter();
 }
-  
+TemplateArgumentList *
+OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
+  switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
+    case Sema::TDK_Success:
+    case Sema::TDK_InstantiationDepth:
+    case Sema::TDK_TooManyArguments:
+    case Sema::TDK_TooFewArguments:
+    case Sema::TDK_Incomplete:
+    case Sema::TDK_InvalidExplicitArguments:
+    case Sema::TDK_Inconsistent:
+    case Sema::TDK_InconsistentQuals:
+      return 0;
+
+    case Sema::TDK_SubstitutionFailure:
+      return static_cast<TemplateArgumentList*>(Data);
+      
+    // Unhandled
+    case Sema::TDK_NonDeducedMismatch:
+    case Sema::TDK_FailedOverloadResolution:
+      break;
+  }
+
+  return 0;
+}
+
 const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
   switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
   case Sema::TDK_Success:
@@ -383,6 +415,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
   case Sema::TDK_TooManyArguments:
   case Sema::TDK_TooFewArguments:
   case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_SubstitutionFailure:
     return 0;
 
   case Sema::TDK_Inconsistent:
@@ -390,7 +423,6 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
     return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;      
 
   // Unhandled
-  case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
     break;
@@ -408,6 +440,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
   case Sema::TDK_TooManyArguments:
   case Sema::TDK_TooFewArguments:
   case Sema::TDK_InvalidExplicitArguments:
+  case Sema::TDK_SubstitutionFailure:
     return 0;
 
   case Sema::TDK_Inconsistent:
@@ -415,7 +448,6 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
     return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
 
   // Unhandled
-  case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
     break;
@@ -5151,11 +5183,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
   case Sema::TDK_TooFewArguments:
     DiagnoseArityMismatch(S, Cand, NumArgs);
     return;
+
+  case Sema::TDK_InstantiationDepth:
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
+    return;
+
+  case Sema::TDK_SubstitutionFailure: {
+    std::string ArgString;
+    if (TemplateArgumentList *Args
+                            = Cand->DeductionFailure.getTemplateArgumentList())
+      ArgString = S.getTemplateArgumentBindingsText(
+                    Fn->getDescribedFunctionTemplate()->getTemplateParameters(),
+                                                    *Args);
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
+      << ArgString;
+    return;
+  }
       
   // TODO: diagnose these individually, then kill off
   // note_ovl_candidate_bad_deduction, which is uselessly vague.
-  case Sema::TDK_InstantiationDepth:
-  case Sema::TDK_SubstitutionFailure:
   case Sema::TDK_NonDeducedMismatch:
   case Sema::TDK_FailedOverloadResolution:
     S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
index c13fb17b858461a5d984703722f76f35552dc98e..cf1694382613d8079b5c063cb4c8a318120bc53b 100644 (file)
@@ -539,6 +539,10 @@ namespace clang {
       /// 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();
index f716ccd6f7ffd8bdbf2c36a31c59ef74095ebc93..aca820dec6e77025f027fcb86639b1ed860bfab5 100644 (file)
@@ -1030,10 +1030,8 @@ FinishTemplateArgumentDeduction(Sema &S,
                                   ClassTemplate->getTemplateParameters(), N);
 
   if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
-                                InstArgs, false, ConvertedInstArgs)) {
-    // FIXME: fail with more useful information?
+                                InstArgs, false, ConvertedInstArgs))
     return Sema::TDK_SubstitutionFailure;
-  }
   
   for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
     TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
@@ -1377,6 +1375,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
                                  NTTP->getDeclName());
             if (NTTPType.isNull()) {
               Info.Param = makeTemplateParameter(Param);
+              Info.reset(new (Context) TemplateArgumentList(Context, Builder, 
+                                                            /*TakeArgs=*/true));
               return TDK_SubstitutionFailure;
             }
           }
@@ -1402,6 +1402,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
                                   : CTAK_Deduced)) {
         Info.Param = makeTemplateParameter(
                          const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+        Info.reset(new (Context) TemplateArgumentList(Context, Builder, 
+                                                      /*TakeArgs=*/true));
         return TDK_SubstitutionFailure;
       }
 
@@ -1432,6 +1434,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
                               CTAK_Deduced)) {
       Info.Param = makeTemplateParameter(
                          const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+      Info.reset(new (Context) TemplateArgumentList(Context, Builder, 
+                                                    /*TakeArgs=*/true));
       return TDK_SubstitutionFailure;
     }
 
@@ -1459,7 +1463,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
   
   // If the template argument list is owned by the function template
   // specialization, release it.
-  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
+  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
+      !Trap.hasErrorOccurred())
     Info.take();
 
   // There may have been an error that did not prevent us from constructing a
index af8bb3924487b0d38c635f38d21c61c9cbf1a91e..bf5f96225daddfa15fc3c6781677090330e1267a 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
 template<int i> class A {  };
-template<short s> void f(A<s>); // expected-note{{failed template argument deduction}}
+template<short s> void f(A<s>); // expected-note{{candidate template ignored: substitution failure}}
 
 void k1() { 
   A<1> a;
@@ -22,7 +22,7 @@ void k3() {
   h<5>(array);
 }
 
-template<short s> void h(int (&)[s], A<s>);  // expected-note{{failed template argument deduction}}
+template<short s> void h(int (&)[s], A<s>);  // expected-note{{candidate template ignored: substitution failure}}
 void k4() {
   A<5> a;
   int array[5];
index 936a6d7aaf5879015198506736469320cb5fa66b..937d633e68b09f498dcc0246bd745792a8cda3af 100644 (file)
@@ -22,3 +22,10 @@ template<template<class T> class, typename T>
 void test_get(void *ptr) {
   get<int>(ptr); // expected-error{{no matching function for call to 'get'}}
 }
+
+template<typename T>
+  typename T::type get_type(const T&); // expected-note{{candidate template ignored: substitution failure [with T = int *]}}
+
+void test_get_type(int *ptr) {
+  (void)get_type(ptr); // expected-error{{no matching function for call to 'get_type'}}
+}