]> granicus.if.org Git - clang/commitdiff
Produce detailed diagnostics when overload
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 23 Sep 2009 00:58:07 +0000 (00:58 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 23 Sep 2009 00:58:07 +0000 (00:58 +0000)
resolution failed to select a candidate due to
ambiguity in type conversion function selection.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOverload.cpp
lib/Sema/SemaOverload.h
test/SemaCXX/ambig-user-defined-convesions.cpp

index a3d15fedc3c83b8e50bf2ff194c33892de747704..2ae2cbe009ca94ca39ef74639ef4837c1e6c73de 100644 (file)
@@ -763,6 +763,8 @@ def err_ovl_ambiguous_member_call : Error<
 def err_ovl_deleted_member_call : Error<
   "call to %select{unavailable|deleted}0 member function %1">;
 def err_ovl_candidate : Note<"candidate function">;
+def err_ovl_candidate_not_viable : Note<"function not viable because"
+                                        " of ambiguity in conversion of argument %0">;
 def err_ovl_template_candidate : Note<
   "candidate function template specialization %0">;
 def err_ovl_candidate_deleted : Note<
index acfc32623644d86998d6669327b338b874cacab9..144cf93d31bbf3e4aed93b5742254d2e02bfab75 100644 (file)
@@ -411,13 +411,15 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
                             bool InOverloadResolution) {
   ImplicitConversionSequence ICS;
   OverloadCandidateSet Conversions;
+  OverloadingResult UserDefResult = OR_Success;
   if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard))
     ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
   else if (getLangOptions().CPlusPlus &&
-           IsUserDefinedConversion(From, ToType, ICS.UserDefined,
+           (UserDefResult = IsUserDefinedConversion(From, ToType, 
+                                   ICS.UserDefined,
                                    Conversions,
                                    !SuppressUserConversions, AllowExplicit,
-                                   ForceRValue) == OR_Success) {
+                                   ForceRValue)) == OR_Success) {
     ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
     // C++ [over.ics.user]p4:
     //   A conversion of an expression of class type to the same class
@@ -454,8 +456,14 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
     if (SuppressUserConversions &&
         ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion)
       ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
-  } else
+  } else {
     ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+    if (UserDefResult == OR_Ambiguous) {
+      for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+           Cand != Conversions.end(); ++Cand)
+        ICS.ConversionFunctionSet.push_back(Cand->Function);
+    }
+  }
 
   return ICS;
 }
@@ -3868,8 +3876,27 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
                               *Cand->Function->getTemplateSpecializationArgs());
         } else {
           // Normal function
-          // FIXME: Give a better reason!
-          Diag(Cand->Function->getLocation(), diag::err_ovl_candidate);
+          bool errReported = false;
+          if (!Cand->Viable && Cand->Conversions.size() > 0) {
+            for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
+              const ImplicitConversionSequence &Conversion = 
+                                                        Cand->Conversions[i];
+              if ((Conversion.ConversionKind != 
+                   ImplicitConversionSequence::BadConversion) ||
+                  Conversion.ConversionFunctionSet.size() == 0)
+                continue;
+              Diag(Cand->Function->getLocation(), 
+                   diag::err_ovl_candidate_not_viable) << (i+1);
+              errReported = true;
+              for (int j = Conversion.ConversionFunctionSet.size()-1; 
+                   j >= 0; j--) {
+                FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
+                Diag(Func->getLocation(), diag::err_ovl_candidate);
+              }
+            }
+          }
+          if (!errReported)
+            Diag(Cand->Function->getLocation(), diag::err_ovl_candidate);
         }
       } else if (Cand->IsSurrogate) {
         // Desugar the type of the surrogate down to a function type,
index 1f3e4df7cbb5dca3772c9e6d624e9273e8a15308..17f559870fdac9d6586391d507faee9dbf185c0a 100644 (file)
@@ -195,7 +195,11 @@ namespace clang {
       /// details of the user-defined conversion sequence.
       UserDefinedConversionSequence UserDefined;
     };
-
+    
+    /// When ConversionKind == BadConversion due to multiple conversion
+    /// functions, this will list those functions.
+    llvm::SmallVector<FunctionDecl*, 4> ConversionFunctionSet;
+    
     // The result of a comparison between implicit conversion
     // sequences. Use Sema::CompareImplicitConversionSequences to
     // actually perform the comparison.
index d391a04d072244a57f025ad950819308a340cc6f..1117253d367be8274c9f516cc2995709cbbc1dd3 100644 (file)
@@ -1,10 +1,10 @@
 // RUN: clang-cc -fsyntax-only -verify %s
 
 struct BASE { 
-  operator int &(); // expected-note {{candidate function}}
+  operator int &(); // expected-note {{candidate function}}
 }; 
 struct BASE1 { 
-  operator int &(); // expected-note {{candidate function}}
+  operator int &(); // expected-note {{candidate function}}
 }; 
 
 struct B : public BASE, BASE1 { 
@@ -13,7 +13,14 @@ struct B : public BASE, BASE1 {
 
 extern B f(); 
 
+B b1;
+void func(const int ci, const char cc); // expected-note {{function not viable because of ambiguity in conversion of argument 1}}
+void func(const char ci, const B b); // expected-note {{function not viable because of ambiguity in conversion of argument 1}}
+void func(const B b, const int ci); // expected-note {{function not viable because of ambiguity in conversion of argument 2}}
+
+
 const int main() {
+  func(b1, f()); // expected-error {{no matching function for call to 'func'}}
   return f(); // expected-error {{conversion from 'struct B' to 'int const' is ambiguous}}
 }