Record some basic information about bad conversion sequences.  Use that
information to feed diagnostics instead of regenerating it.  Much room for
improvement here, but fixes some unfortunate problems reporting on method calls.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93316 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e10398a..edeb7c1 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4389,7 +4389,10 @@
     = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
 
   // Most paths end in a failed conversion.
-  if (ICS) ICS->setBad();
+  if (ICS) {
+    ICS->setBad();
+    ICS->Bad.init(BadConversionSequence::no_conversion, Init, DeclType);
+  }
 
   // C++ [dcl.init.ref]p5:
   //   A reference to type "cv1 T1" is initialized by an expression
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d694798..d10e11f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1076,6 +1076,7 @@
                                 bool Elidable,
                                 ImplicitConversionSequence& ICS) {
   ICS.setBad();
+  ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
   if (Elidable && getLangOptions().CPlusPlus0x) {
     ICS = TryImplicitConversion(From, ToType,
                                 /*SuppressUserConversions=*/false,
@@ -1942,7 +1943,7 @@
 
   ImplicitConversionSequence E1ToC2, E2ToC2;
   E1ToC2.setBad();
-  E2ToC2.setBad();
+  E2ToC2.setBad();  
   if (Context.getCanonicalType(Composite1) !=
       Context.getCanonicalType(Composite2)) {
     E1ToC2 = TryImplicitConversion(E1, Composite2,
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 4f299ff..ffcf8d4 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -489,8 +489,10 @@
     //   of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
     //   13.3.1.6 in all cases, only standard conversion sequences and
     //   ellipsis conversion sequences are allowed.
-    if (SuppressUserConversions && ICS.isUserDefined())
+    if (SuppressUserConversions && ICS.isUserDefined()) {
       ICS.setBad();
+      ICS.Bad.init(BadConversionSequence::suppressed_user, From, ToType);
+    }
   } else if (UserDefResult == OR_Ambiguous) {
     ICS.setAmbiguous();
     ICS.Ambiguous.setFromType(From->getType());
@@ -501,6 +503,7 @@
         ICS.Ambiguous.addConversion(Cand->Function);
   } else {
     ICS.setBad();
+    ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
   }
 
   return ICS;
@@ -2129,6 +2132,7 @@
                             bool InOverloadResolution) {
   if (ToType->isReferenceType()) {
     ImplicitConversionSequence ICS;
+    ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType);
     CheckReferenceInit(From, ToType,
                        /*FIXME:*/From->getLocStart(),
                        SuppressUserConversions,
@@ -2223,8 +2227,10 @@
   QualType FromTypeCanon = Context.getCanonicalType(FromType);
   if (ImplicitParamType.getCVRQualifiers() 
                                     != FromTypeCanon.getLocalCVRQualifiers() &&
-      !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon))
+      !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) {
+    ICS.Bad.init(BadConversionSequence::bad_qualifiers, FromType, ImplicitParamType);
     return ICS;
+  }
 
   // Check that we have either the same type or a derived type. It
   // affects the conversion rank.
@@ -2233,8 +2239,10 @@
     ICS.Standard.Second = ICK_Identity;
   else if (IsDerivedFrom(FromType, ClassType))
     ICS.Standard.Second = ICK_Derived_To_Base;
-  else
+  else {
+    ICS.Bad.init(BadConversionSequence::unrelated_class, FromType, ImplicitParamType);
     return ICS;
+  }
 
   // Success. Mark this as a reference binding.
   ICS.setStandard();
@@ -2385,6 +2393,7 @@
   if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto && 
       !Proto->isVariadic()) {
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
     return;
   }
 
@@ -2397,6 +2406,7 @@
   if (NumArgs < MinRequiredArgs && !PartialOverloading) {
     // Not enough arguments.
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
     return;
   }
 
@@ -2416,6 +2426,7 @@
                                 /*InOverloadResolution=*/true);
       if (Candidate.Conversions[ArgIdx].isBad()) {
         Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
         break;
       }
     } else {
@@ -2532,6 +2543,7 @@
   // list (8.3.5).
   if (NumArgs > NumArgsInProto && !Proto->isVariadic()) {
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
     return;
   }
 
@@ -2544,6 +2556,7 @@
   if (NumArgs < MinRequiredArgs) {
     // Not enough arguments.
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
     return;
   }
 
@@ -2560,6 +2573,7 @@
       = TryObjectArgumentInitialization(ObjectType, Method, ActingContext);
     if (Candidate.Conversions[0].isBad()) {
       Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
       return;
     }
   }
@@ -2579,6 +2593,7 @@
                                 /*InOverloadResolution=*/true);
       if (Candidate.Conversions[ArgIdx + 1].isBad()) {
         Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
         break;
       }
     } else {
@@ -2670,6 +2685,7 @@
     OverloadCandidate &Candidate = CandidateSet.back();
     Candidate.Function = FunctionTemplate->getTemplatedDecl();
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_deduction;
     Candidate.IsSurrogate = false;
     Candidate.IgnoreObjectArgument = false;
     return;
@@ -2726,6 +2742,7 @@
     Candidate.Conversions[0].Standard.Second = ICK_Identity;
   if (Candidate.Conversions[0].isBad()) {
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
     return;
   }
   
@@ -2737,6 +2754,7 @@
   QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType();
   if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) {
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
     return;
   }
   
@@ -2774,6 +2792,7 @@
 
   case ImplicitConversionSequence::BadConversion:
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
     break;
 
   default:
@@ -2847,6 +2866,7 @@
     = TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
   if (ObjectInit.isBad()) {
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_bad_conversion;
     return;
   }
 
@@ -2869,6 +2889,7 @@
   // list (8.3.5).
   if (NumArgs > NumArgsInProto && !Proto->isVariadic()) {
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_many_arguments;
     return;
   }
 
@@ -2877,6 +2898,7 @@
   if (NumArgs < NumArgsInProto) {
     // Not enough arguments.
     Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_too_few_arguments;
     return;
   }
 
@@ -2896,6 +2918,7 @@
                                 /*InOverloadResolution=*/false);
       if (Candidate.Conversions[ArgIdx + 1].isBad()) {
         Candidate.Viable = false;
+        Candidate.FailureKind = ovl_fail_bad_conversion;
         break;
       }
     } else {
@@ -3038,6 +3061,7 @@
     }
     if (Candidate.Conversions[ArgIdx].isBad()) {
       Candidate.Viable = false;
+      Candidate.FailureKind = ovl_fail_bad_conversion;
       break;
     }
   }
@@ -4336,36 +4360,69 @@
 
 namespace {
 
-void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I,
-                           Expr **Args, unsigned NumArgs) {
+void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) {
+  const ImplicitConversionSequence &Conv = Cand->Conversions[I];
+  assert(Conv.isBad());
   assert(Cand->Function && "for now, candidate must be a function");
   FunctionDecl *Fn = Cand->Function;
 
   // There's a conversion slot for the object argument if this is a
   // non-constructor method.  Note that 'I' corresponds the
   // conversion-slot index.
+  bool isObjectArgument = false;
   if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn)) {
-    // FIXME: talk usefully about bad conversions for object arguments.
-    if (I == 0) return S.NoteOverloadCandidate(Fn);
-    else I--;
+    if (I == 0)
+      isObjectArgument = true;
+    else
+      I--;
   }
 
-  // FIXME: can we have a bad conversion on an ellipsis parameter?
-  assert(I < NumArgs && "index exceeds number of formal arguments");
-  assert(I < Fn->getType()->getAs<FunctionProtoType>()->getNumArgs() &&
-         "index exceeds number of formal parameters");
-
   std::string FnDesc;
   OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
 
-  QualType FromTy = Args[I]->getType();
-  QualType ToTy = Fn->getType()->getAs<FunctionProtoType>()->getArgType(I);
+  Expr *FromExpr = Conv.Bad.FromExpr;
+  QualType FromTy = Conv.Bad.getFromType();
+  QualType ToTy = Conv.Bad.getToType();
 
   // TODO: specialize based on the kind of mismatch
   S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv)
     << (unsigned) FnKind << FnDesc
-    << Args[I]->getSourceRange() << FromTy << ToTy
-    << I+1;
+    << (FromExpr ? FromExpr->getSourceRange() : SourceRange())
+    << FromTy << ToTy << I+1;
+}
+
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+                           unsigned NumFormalArgs) {
+  // TODO: treat calls to a missing default constructor as a special case
+
+  FunctionDecl *Fn = Cand->Function;
+  const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+
+  unsigned MinParams = Fn->getMinRequiredArguments();
+  
+  // at least / at most / exactly
+  unsigned mode, modeCount;
+  if (NumFormalArgs < MinParams) {
+    assert(Cand->FailureKind == ovl_fail_too_few_arguments);
+    if (MinParams != FnTy->getNumArgs() || FnTy->isVariadic())
+      mode = 0; // "at least"
+    else
+      mode = 2; // "exactly"
+    modeCount = MinParams;
+  } else {
+    assert(Cand->FailureKind == ovl_fail_too_many_arguments);
+    if (MinParams != FnTy->getNumArgs())
+      mode = 1; // "at most"
+    else
+      mode = 2; // "exactly"
+    modeCount = FnTy->getNumArgs();
+  }
+
+  std::string Description;
+  OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
+
+  S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
+    << (unsigned) FnKind << Description << mode << modeCount << NumFormalArgs;
 }
 
 void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
@@ -4388,52 +4445,24 @@
     return;
   }
 
-  // Diagnose arity mismatches.
-  // TODO: treat calls to a missing default constructor as a special case
-  unsigned NumFormalArgs = NumArgs;
-  if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn))
-    NumFormalArgs--;
-  const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
-  unsigned MinParams = Fn->getMinRequiredArguments();
-  if (NumFormalArgs < MinParams ||
-      (NumFormalArgs > FnTy->getNumArgs() && !FnTy->isVariadic())) {
-    std::string Description;
-    OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
+  switch (Cand->FailureKind) {
+  case ovl_fail_too_many_arguments:
+  case ovl_fail_too_few_arguments:
+    return DiagnoseArityMismatch(S, Cand, NumArgs);
 
-    // at least / at most / exactly
-    unsigned mode, modeCount;
-    if (NumFormalArgs < MinParams) {
-      if (MinParams != FnTy->getNumArgs())
-        mode = 0; // "at least"
-      else
-        mode = 2; // "exactly"
-      modeCount = MinParams;
-    } else {
-      if (MinParams != FnTy->getNumArgs())
-        mode = 1; // "at most"
-      else
-        mode = 2; // "exactly"
-      modeCount = FnTy->getNumArgs();
-    }
+  case ovl_fail_bad_deduction:
+    return S.NoteOverloadCandidate(Fn);
 
-    S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity)
-      << (unsigned) FnKind << Description << mode << modeCount << NumFormalArgs;
-    return;
+  case ovl_fail_bad_conversion:
+    for (unsigned I = 0, N = Cand->Conversions.size(); I != N; ++I)
+      if (Cand->Conversions[I].isBad())
+        return DiagnoseBadConversion(S, Cand, I);
+    
+    // FIXME: this currently happens when we're called from SemaInit
+    // when user-conversion overload fails.  Figure out how to handle
+    // those conditions and diagnose them well.
+    return S.NoteOverloadCandidate(Fn);
   }
-
-  // Look for bad conversions.
-  if (!Cand->Conversions.empty()) {
-    for (unsigned I = 0, N = Cand->Conversions.size(); I != N; ++I) {
-      if (!Cand->Conversions[I].isBad())
-        continue;
-
-      DiagnoseBadConversion(S, Cand, I, Args, NumArgs);
-      return;
-    }
-  }
-
-  // Give up and give the generic message.
-  S.NoteOverloadCandidate(Fn);
 }
 
 void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index 78fa05b..20add00 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_SEMA_OVERLOAD_H
 
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
@@ -241,6 +242,51 @@
     void copyFrom(const AmbiguousConversionSequence &);
   };
 
+  /// BadConversionSequence - Records information about an invalid
+  /// conversion sequence.
+  struct BadConversionSequence {
+    enum FailureKind {
+      no_conversion,
+      unrelated_class,
+      suppressed_user,
+      bad_qualifiers
+    };
+
+    // This can be null, e.g. for implicit object arguments.
+    Expr *FromExpr;
+
+    FailureKind Kind;
+
+  private:
+    // The type we're converting from (an opaque QualType).
+    void *FromTy;
+
+    // The type we're converting to (an opaque QualType).
+    void *ToTy;
+
+  public:
+    void init(FailureKind K, Expr *From, QualType To) {
+      init(K, From->getType(), To);
+      FromExpr = From;
+    }
+    void init(FailureKind K, QualType From, QualType To) {
+      Kind = K;
+      FromExpr = 0;
+      setFromType(From);
+      setToType(To);
+    }
+
+    QualType getFromType() const { return QualType::getFromOpaquePtr(FromTy); }
+    QualType getToType() const { return QualType::getFromOpaquePtr(ToTy); }
+
+    void setFromExpr(Expr *E) {
+      FromExpr = E;
+      setFromType(E->getType());
+    }
+    void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); }
+    void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); }
+  };
+
   /// ImplicitConversionSequence - Represents an implicit conversion
   /// sequence, which may be a standard conversion sequence
   /// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
@@ -280,6 +326,10 @@
       /// When ConversionKind == AmbiguousConversion, provides the
       /// details of the ambiguous conversion.
       AmbiguousConversionSequence Ambiguous;
+
+      /// When ConversionKind == BadConversion, provides the details
+      /// of the bad conversion.
+      BadConversionSequence Bad;
     };
 
     ImplicitConversionSequence() : ConversionKind(BadConversion) {}
@@ -294,7 +344,7 @@
       case UserDefinedConversion: UserDefined = Other.UserDefined; break;
       case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
       case EllipsisConversion: break;
-      case BadConversion: break;
+      case BadConversion: Bad = Other.Bad; break;
       }
     }
 
@@ -336,6 +386,13 @@
     void DebugPrint() const;
   };
 
+  enum OverloadFailureKind {
+    ovl_fail_too_many_arguments,
+    ovl_fail_too_few_arguments,
+    ovl_fail_bad_conversion,
+    ovl_fail_bad_deduction
+  };
+
   /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).
   struct OverloadCandidate {
     /// Function - The actual function that this candidate
@@ -376,6 +433,10 @@
     /// object argument.
     bool IgnoreObjectArgument;
 
+    /// FailureKind - The reason why this candidate is not viable.
+    /// Actually an OverloadFailureKind.
+    unsigned char FailureKind;
+
     /// FinalConversion - For a conversion function (where Function is
     /// a CXXConversionDecl), the standard conversion that occurs
     /// after the call to the overload candidate to convert the result