[cfe-commits] r93224 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaOverload.cpp test/SemaCXX/overload-call.cpp

John McCall rjmccall at apple.com
Mon Jan 11 18:15:36 PST 2010


Author: rjmccall
Date: Mon Jan 11 20:15:36 2010
New Revision: 93224

URL: http://llvm.org/viewvc/llvm-project?rev=93224&view=rev
Log:
Reorganize some of the code to note overload candidates.  Improves the
fidelity with which we note them as functions/constructors and templates
thereof.  Also will be helpful when reporting bad conversions (next).


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/overload-call.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 11 20:15:36 2010
@@ -895,23 +895,23 @@
   "call to member function %0 is ambiguous">;
 def err_ovl_deleted_member_call : Error<
   "call to %select{unavailable|deleted}0 member function %1">;
-def note_ovl_candidate : Note<"candidate function">;
+def note_ovl_candidate : Note<"candidate "
+    "%select{function|function|constructor|"
+    "is the implicit default constructor|"
+    "is the implicit copy constructor|"
+    "is the implicit copy assignment operator}0">;
+def note_ovl_template_candidate : Note<
+  "candidate function template specialization %0">;
+def note_ovl_candidate_deleted : Note<
+  "candidate %select{function|function|constructor}0 has been explicitly "
+  "%select{made unavailable|deleted}1">;
+def note_ovl_template_candidate_deleted : Note<
+  "candidate function template specialization %0 has been explicit "
+  "&select{made unavailable|deleted}1">;
 def note_ovl_candidate_not_viable : Note<"function not viable because"
                           " of ambiguity in conversion of argument %0">;
-def note_ovl_candidate_ctor : Note<"candidate constructor">;
-def note_ovl_candidate_implicit_copy_ctor : Note<
-    "candidate is the implicit copy constructor">;
-def note_ovl_candidate_implicit_default_ctor : Note<
-    "candidate is the implicit default constructor">;
-def note_ovl_candidate_meth : Note<"candidate function">;
-def note_ovl_candidate_implicit_copy_assign : Note<
-    "candidate is the implicit copy assignment operator">;
 def note_ambiguous_type_conversion: Note<
     "because of ambiguity in conversion of %0 to %1">;
-def note_ovl_template_candidate : Note<
-  "candidate function template specialization %0">;
-def note_ovl_candidate_deleted : Note<
-  "candidate function has been explicitly %select{made unavailable|deleted}0">;
 def note_ovl_builtin_binary_candidate : Note<
     "built-in candidate %0">;
 def note_ovl_builtin_unary_candidate : Note<

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jan 11 20:15:36 2010
@@ -4263,42 +4263,62 @@
   return OR_Success;
 }
 
-/// Notes the location of an overload candidate.
-void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
+namespace {
 
-  if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
-    // At least call it a 'constructor'.
-    if (!Ctor->isImplicit()) {
-      Diag(Ctor->getLocation(), diag::note_ovl_candidate_ctor);
-      return;
-    }
+enum OverloadCandidateKind {
+  oc_function,
+  oc_method,
+  oc_constructor,
+  oc_implicit_default_constructor,
+  oc_implicit_copy_constructor,
+  oc_implicit_copy_assignment,
+  oc_template_specialization // function, constructor, or conversion template
+};
 
-    CXXRecordDecl *Record = Ctor->getParent();
-    if (Ctor->isCopyConstructor()) {
-      Diag(Record->getLocation(), diag::note_ovl_candidate_implicit_copy_ctor);
-      return;
-    }
+OverloadCandidateKind ClassifyOverloadCandidate(FunctionDecl *Fn) {
+  if (Fn->getPrimaryTemplate())
+    return oc_template_specialization;
 
-    Diag(Record->getLocation(), diag::note_ovl_candidate_implicit_default_ctor);
-    return;
+  if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) {
+    if (!Ctor->isImplicit())
+      return oc_constructor;
+
+    return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor
+                                     : oc_implicit_default_constructor;
   }
 
   if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) {
     // This actually gets spelled 'candidate function' for now, but
     // it doesn't hurt to split it out.
-    if (!Meth->isImplicit()) {
-      Diag(Meth->getLocation(), diag::note_ovl_candidate_meth);
-      return;
-    }
+    if (!Meth->isImplicit())
+      return oc_method;
 
     assert(Meth->isCopyAssignment()
            && "implicit method is not copy assignment operator?");
-    Diag(Meth->getParent()->getLocation(),
-         diag::note_ovl_candidate_implicit_copy_assign);
+    return oc_implicit_copy_assignment;
+  }
+
+  return oc_function;
+}
+
+std::string DescribeFunctionTemplate(Sema &S, FunctionDecl *Fn) {
+  FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate();
+  return S.getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(),
+                                       *Fn->getTemplateSpecializationArgs());
+}
+
+} // end anonymous namespace
+
+// Notes the location of an overload candidate.
+void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
+  OverloadCandidateKind K = ClassifyOverloadCandidate(Fn);
+  if (K == oc_template_specialization) {
+    Diag(Fn->getLocation(), diag::note_ovl_template_candidate)
+      << DescribeFunctionTemplate(*this, Fn);
     return;
   }
 
-  Diag(Fn->getLocation(), diag::note_ovl_candidate);
+  Diag(Fn->getLocation(), diag::note_ovl_candidate) << (unsigned) K;
 }
 
 /// Diagnoses an ambiguous conversion.  The partial diagnostic is the
@@ -4318,26 +4338,23 @@
 namespace {
 
 void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
+  FunctionDecl *Fn = Cand->Function;
+
   // Note deleted candidates, but only if they're viable.
-  if (Cand->Viable &&
-      (Cand->Function->isDeleted() ||
-       Cand->Function->hasAttr<UnavailableAttr>())) {
-    S.Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted)
-      << Cand->Function->isDeleted();
-    return;
-  }
+  if (Cand->Viable && (Fn->isDeleted() || Fn->hasAttr<UnavailableAttr>())) {
+    OverloadCandidateKind FnKind = ClassifyOverloadCandidate(Fn);
+
+    if (FnKind == oc_template_specialization) {
+      S.Diag(Fn->getLocation(), diag::note_ovl_template_candidate_deleted)
+        << DescribeFunctionTemplate(S, Fn) << Fn->isDeleted();
+      return;
+    }
 
-  if (FunctionTemplateDecl *FunTmpl 
-               = Cand->Function->getPrimaryTemplate()) {
-    // Function template specialization
-    // FIXME: Give a better reason!
-    S.Diag(Cand->Function->getLocation(), diag::note_ovl_template_candidate)
-      << S.getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(),
-                              *Cand->Function->getTemplateSpecializationArgs());
+    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
+      << FnKind << Fn->isDeleted();
     return;
   }
 
-  // Normal function
   bool errReported = false;
   if (!Cand->Viable && Cand->Conversions.size() > 0) {
     for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
@@ -4347,14 +4364,14 @@
       if (!Conversion.isAmbiguous())
         continue;
 
-      S.DiagnoseAmbiguousConversion(Conversion, Cand->Function->getLocation(),
+      S.DiagnoseAmbiguousConversion(Conversion, Fn->getLocation(),
                          PDiag(diag::note_ovl_candidate_not_viable) << (i+1));
       errReported = true;
     }
   }
 
   if (!errReported)
-    S.NoteOverloadCandidate(Cand->Function);
+    S.NoteOverloadCandidate(Fn);
 }
 
 void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {

Modified: cfe/trunk/test/SemaCXX/overload-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-call.cpp?rev=93224&r1=93223&r2=93224&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/overload-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-call.cpp Mon Jan 11 20:15:36 2010
@@ -301,3 +301,13 @@
     (void)ir;
   }
 }
+
+// Tests the exact text used to note the candidates
+namespace test1 {
+  template <class T> void foo(T t, unsigned N); // expected-note {{candidate function template specialization [with T = int]}}
+  void foo(int n, char N); // expected-note {{candidate function}} 
+
+  void test() {
+    foo(4, "hello"); //expected-error {{no matching function for call to 'foo'}}
+  }
+}





More information about the cfe-commits mailing list