[cfe-commits] r93214 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/ambig-user-defined-conversions.cpp test/SemaCXX/builtin-ptrtomember-overload-1.cpp test/SemaCXX/conditional-expr.cpp

John McCall rjmccall at apple.com
Mon Jan 11 16:44:58 PST 2010


Author: rjmccall
Date: Mon Jan 11 18:44:57 2010
New Revision: 93214

URL: http://llvm.org/viewvc/llvm-project?rev=93214&view=rev
Log:
Introduce a specific representation for the ambiguous implicit conversion
sequence.  Lots of small relevant changes.  Fixes some serious problems with
ambiguous conversions;  also possibly improves associated diagnostics.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCXXCast.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaOverload.h
    cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp
    cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp
    cfe/trunk/test/SemaCXX/conditional-expr.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=93214&r1=93213&r2=93214&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan 11 18:44:57 2010
@@ -1044,6 +1044,9 @@
                                SourceLocation Loc = SourceLocation());
 
   void NoteOverloadCandidate(FunctionDecl *Fn);
+  void DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
+                                   SourceLocation CaretLoc,
+                                   const PartialDiagnostic &PDiag);
 
   FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
                                                    bool Complain);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Mon Jan 11 18:44:57 2010
@@ -893,7 +893,7 @@
                                /*InOverloadResolution=*/false,
                                /*one of user provided casts*/true);
 
-  if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
+  if (ICS.isBad())
     return TC_NotApplicable;
 
   // The conversion is possible, so commit to it.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan 11 18:44:57 2010
@@ -4389,8 +4389,7 @@
     = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
 
   // Most paths end in a failed conversion.
-  if (ICS)
-    ICS->ConversionKind = ImplicitConversionSequence::BadConversion;
+  if (ICS) ICS->setBad();
 
   // C++ [dcl.init.ref]p5:
   //   A reference to type "cv1 T1" is initialized by an expression
@@ -4428,7 +4427,7 @@
       //   has a type that is a derived class of the parameter type,
       //   in which case the implicit conversion sequence is a
       //   derived-to-base Conversion (13.3.3.1).
-      ICS->ConversionKind = ImplicitConversionSequence::StandardConversion;
+      ICS->setStandard();
       ICS->Standard.First = ICK_Identity;
       ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
       ICS->Standard.Third = ICK_Identity;
@@ -4513,7 +4512,7 @@
         //   conversion or, if the conversion function returns an
         //   entity of a type that is a derived class of the parameter
         //   type, a derived-to-base Conversion.
-        ICS->ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
+        ICS->setUserDefined();
         ICS->UserDefined.Before = Best->Conversions[0].Standard;
         ICS->UserDefined.After = Best->FinalConversion;
         ICS->UserDefined.ConversionFunction = Best->Function;
@@ -4539,10 +4538,11 @@
 
     case OR_Ambiguous:
       if (ICS) {
+        ICS->setAmbiguous();
         for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
              Cand != CandidateSet.end(); ++Cand)
           if (Cand->Viable)
-            ICS->ConversionFunctionSet.push_back(Cand->Function);
+            ICS->Ambiguous.addConversion(Cand->Function);
         break;
       }
       Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType()
@@ -4616,7 +4616,7 @@
   if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
       RefRelationship >= Ref_Compatible_With_Added_Qualification) {
     if (ICS) {
-      ICS->ConversionKind = ImplicitConversionSequence::StandardConversion;
+      ICS->setStandard();
       ICS->Standard.First = ICK_Identity;
       ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
       ICS->Standard.Third = ICK_Identity;
@@ -4688,29 +4688,26 @@
                                  /*InOverloadResolution=*/false);
 
     // Of course, that's still a reference binding.
-    if (ICS->ConversionKind == ImplicitConversionSequence::StandardConversion) {
+    if (ICS->isStandard()) {
       ICS->Standard.ReferenceBinding = true;
       ICS->Standard.RRefBinding = isRValRef;
-    } else if (ICS->ConversionKind ==
-              ImplicitConversionSequence::UserDefinedConversion) {
+    } else if (ICS->isUserDefined()) {
       ICS->UserDefined.After.ReferenceBinding = true;
       ICS->UserDefined.After.RRefBinding = isRValRef;
     }
-    return ICS->ConversionKind == ImplicitConversionSequence::BadConversion;
+    return ICS->isBad();
   } else {
     ImplicitConversionSequence Conversions;
     bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing, 
                                                    false, false, 
                                                    Conversions);
     if (badConversion) {
-      if ((Conversions.ConversionKind  == 
-            ImplicitConversionSequence::BadConversion)
-          && !Conversions.ConversionFunctionSet.empty()) {
+      if (Conversions.isAmbiguous()) {
         Diag(DeclLoc, 
              diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange();
-        for (int j = Conversions.ConversionFunctionSet.size()-1; 
+        for (int j = Conversions.Ambiguous.conversions().size()-1; 
              j >= 0; j--) {
-          FunctionDecl *Func = Conversions.ConversionFunctionSet[j];
+          FunctionDecl *Func = Conversions.Ambiguous.conversions()[j];
           NoteOverloadCandidate(Func);
         }
       }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Jan 11 18:44:57 2010
@@ -1075,7 +1075,7 @@
                                 AssignmentAction Action, bool AllowExplicit,
                                 bool Elidable,
                                 ImplicitConversionSequence& ICS) {
-  ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+  ICS.setBad();
   if (Elidable && getLangOptions().CPlusPlus0x) {
     ICS = TryImplicitConversion(From, ToType,
                                 /*SuppressUserConversions=*/false,
@@ -1083,7 +1083,7 @@
                                 /*ForceRValue=*/true,
                                 /*InOverloadResolution=*/false);
   }
-  if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+  if (ICS.isBad()) {
     ICS = TryImplicitConversion(From, ToType,
                                 /*SuppressUserConversions=*/false,
                                 AllowExplicit,
@@ -1103,7 +1103,7 @@
 Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
                                 const ImplicitConversionSequence &ICS,
                                 AssignmentAction Action, bool IgnoreBaseAccess) {
-  switch (ICS.ConversionKind) {
+  switch (ICS.getKind()) {
   case ImplicitConversionSequence::StandardConversion:
     if (PerformImplicitConversion(From, ToType, ICS.Standard, Action,
                                   IgnoreBaseAccess))
@@ -1157,6 +1157,12 @@
       return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
                                        AA_Converting, IgnoreBaseAccess);
   }
+
+  case ImplicitConversionSequence::AmbiguousConversion:
+    DiagnoseAmbiguousConversion(ICS, From->getExprLoc(),
+                          PDiag(diag::err_typecheck_ambiguous_condition)
+                            << From->getSourceRange());
+     return true;
       
   case ImplicitConversionSequence::EllipsisConversion:
     assert(false && "Cannot perform an ellipsis conversion");
@@ -1474,14 +1480,18 @@
 
 /// \brief Get the target type of a standard or user-defined conversion.
 static QualType TargetType(const ImplicitConversionSequence &ICS) {
-  assert((ICS.ConversionKind ==
-              ImplicitConversionSequence::StandardConversion ||
-          ICS.ConversionKind ==
-              ImplicitConversionSequence::UserDefinedConversion) &&
-         "function only valid for standard or user-defined conversions");
-  if (ICS.ConversionKind == ImplicitConversionSequence::StandardConversion)
-    return QualType::getFromOpaquePtr(ICS.Standard.ToTypePtr);
-  return QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr);
+  switch (ICS.getKind()) {
+  case ImplicitConversionSequence::StandardConversion:
+    return ICS.Standard.getToType();
+  case ImplicitConversionSequence::UserDefinedConversion:
+    return ICS.UserDefined.After.getToType();
+  case ImplicitConversionSequence::AmbiguousConversion:
+    return ICS.Ambiguous.getToType();
+  case ImplicitConversionSequence::EllipsisConversion:
+  case ImplicitConversionSequence::BadConversion:
+    llvm_unreachable("function not valid for ellipsis or bad conversions");
+  }
+  return QualType(); // silence warnings
 }
 
 /// \brief Try to convert a type to another according to C++0x 5.16p3.
@@ -1511,19 +1521,16 @@
                                  /*ForceRValue=*/false,
                                  &ICS))
     {
-      assert((ICS.ConversionKind ==
-                  ImplicitConversionSequence::StandardConversion ||
-              ICS.ConversionKind ==
-                  ImplicitConversionSequence::UserDefinedConversion) &&
+      assert((ICS.isStandard() || ICS.isUserDefined()) &&
              "expected a definite conversion");
       bool DirectBinding =
-        ICS.ConversionKind == ImplicitConversionSequence::StandardConversion ?
-        ICS.Standard.DirectBinding : ICS.UserDefined.After.DirectBinding;
+        ICS.isStandard() ? ICS.Standard.DirectBinding
+                         : ICS.UserDefined.After.DirectBinding;
       if (DirectBinding)
         return false;
     }
   }
-  ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+  ICS.setBad();
   //   -- If E2 is an rvalue, or if the conversion above cannot be done:
   //      -- if E1 and E2 have class type, and the underlying class types are
   //         the same or one is a base class of the other:
@@ -1619,8 +1626,7 @@
 /// handles the reference binding specially.
 static bool ConvertForConditional(Sema &Self, Expr *&E,
                                   const ImplicitConversionSequence &ICS) {
-  if (ICS.ConversionKind == ImplicitConversionSequence::StandardConversion &&
-      ICS.Standard.ReferenceBinding) {
+  if (ICS.isStandard() && ICS.Standard.ReferenceBinding) {
     assert(ICS.Standard.DirectBinding &&
            "TryClassUnification should never generate indirect ref bindings");
     // FIXME: CheckReferenceInit should be able to reuse the ICS instead of
@@ -1632,8 +1638,7 @@
                                    /*AllowExplicit=*/false,
                                    /*ForceRValue=*/false);
   }
-  if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion &&
-      ICS.UserDefined.After.ReferenceBinding) {
+  if (ICS.isUserDefined() && ICS.UserDefined.After.ReferenceBinding) {
     assert(ICS.UserDefined.After.DirectBinding &&
            "TryClassUnification should never generate indirect ref bindings");
     return Self.CheckReferenceInit(E, Self.Context.getLValueReferenceType(
@@ -1721,10 +1726,8 @@
     if (TryClassUnification(*this, RHS, LHS, QuestionLoc, ICSRightToLeft))
       return QualType();
 
-    bool HaveL2R = ICSLeftToRight.ConversionKind !=
-      ImplicitConversionSequence::BadConversion;
-    bool HaveR2L = ICSRightToLeft.ConversionKind !=
-      ImplicitConversionSequence::BadConversion;
+    bool HaveL2R = !ICSLeftToRight.isBad();
+    bool HaveR2L = !ICSRightToLeft.isBad();
     //   If both can be converted, [...] the program is ill-formed.
     if (HaveL2R && HaveR2L) {
       Diag(QuestionLoc, diag::err_conditional_ambiguous)
@@ -1938,8 +1941,8 @@
                           /*InOverloadResolution=*/false);
 
   ImplicitConversionSequence E1ToC2, E2ToC2;
-  E1ToC2.ConversionKind = ImplicitConversionSequence::BadConversion;
-  E2ToC2.ConversionKind = ImplicitConversionSequence::BadConversion;
+  E1ToC2.setBad();
+  E2ToC2.setBad();
   if (Context.getCanonicalType(Composite1) !=
       Context.getCanonicalType(Composite2)) {
     E1ToC2 = TryImplicitConversion(E1, Composite2,
@@ -1954,14 +1957,8 @@
                                    /*InOverloadResolution=*/false);
   }
 
-  bool ToC1Viable = E1ToC1.ConversionKind !=
-                      ImplicitConversionSequence::BadConversion
-                 && E2ToC1.ConversionKind !=
-                      ImplicitConversionSequence::BadConversion;
-  bool ToC2Viable = E1ToC2.ConversionKind !=
-                      ImplicitConversionSequence::BadConversion
-                 && E2ToC2.ConversionKind !=
-                      ImplicitConversionSequence::BadConversion;
+  bool ToC1Viable = !E1ToC1.isBad() && !E2ToC1.isBad();
+  bool ToC2Viable = !E1ToC2.isBad() && !E2ToC2.isBad();
   if (ToC1Viable && !ToC2Viable) {
     if (!PerformImplicitConversion(E1, Composite1, E1ToC1, Sema::AA_Converting) &&
         !PerformImplicitConversion(E2, Composite1, E2ToC1, Sema::AA_Converting))

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Jan 11 18:44:57 2010
@@ -670,7 +670,7 @@
                                         /*ForceRValue=*/false,
                                         /*InOverloadResolution=*/false);
 
-      if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) {
+      if (!ICS.isBad()) {
         if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS,
                                               Sema::AA_Initializing))
           hadError = true;
@@ -2300,6 +2300,11 @@
                                                        Sequence);
       if (ConvOvlResult == OR_Success)
         return;
+      if (ConvOvlResult != OR_No_Viable_Function) {
+        Sequence.SetOverloadFailure(
+                      InitializationSequence::FK_ReferenceInitOverloadFailed,
+                                    ConvOvlResult);
+      }
     }
   }
   
@@ -2384,7 +2389,7 @@
                               /*FIXME:InOverloadResolution=*/false,
                               /*UserCast=*/Kind.isExplicitCast());
             
-  if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+  if (ICS.isBad()) {
     // FIXME: Use the conversion function set stored in ICS to turn
     // this into an overloading ambiguity diagnostic. However, we need
     // to keep that set as an OverloadCandidateSet rather than as some
@@ -2685,14 +2690,14 @@
   
   // Perform overload resolution. If it fails, return the failed result.  
   OverloadCandidateSet::iterator Best;
-  if (OverloadingResult Result 
+  if (OverloadingResult Result
         = S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
     Sequence.SetOverloadFailure(
                         InitializationSequence::FK_UserConversionOverloadFailed, 
                                 Result);
     return;
   }
-  
+
   FunctionDecl *Function = Best->Function;
   
   if (isa<CXXConstructorDecl>(Function)) {
@@ -2711,7 +2716,7 @@
   if (Best->FinalConversion.First || Best->FinalConversion.Second ||
       Best->FinalConversion.Third) {
     ImplicitConversionSequence ICS;
-    ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+    ICS.setStandard();
     ICS.Standard = Best->FinalConversion;
     Sequence.AddConversionSequenceStep(ICS, DestType);
   }
@@ -2732,7 +2737,7 @@
                               /*FIXME:InOverloadResolution=*/false,
                               /*UserCast=*/Kind.isExplicitCast());
   
-  if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+  if (ICS.isBad()) {
     Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
     return;
   }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jan 11 18:44:57 2010
@@ -145,15 +145,12 @@
 /// used as part of the ranking of standard conversion sequences
 /// (C++ 13.3.3.2p4).
 bool StandardConversionSequence::isPointerConversionToBool() const {
-  QualType FromType = QualType::getFromOpaquePtr(FromTypePtr);
-  QualType ToType = QualType::getFromOpaquePtr(ToTypePtr);
-
   // Note that FromType has not necessarily been transformed by the
   // array-to-pointer or function-to-pointer implicit conversions, so
   // check for their presence as well as checking whether FromType is
   // a pointer.
-  if (ToType->isBooleanType() &&
-      (FromType->isPointerType() || FromType->isBlockPointerType() ||
+  if (getToType()->isBooleanType() &&
+      (getFromType()->isPointerType() || getFromType()->isBlockPointerType() ||
        First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
     return true;
 
@@ -167,8 +164,8 @@
 bool
 StandardConversionSequence::
 isPointerConversionToVoidPointer(ASTContext& Context) const {
-  QualType FromType = QualType::getFromOpaquePtr(FromTypePtr);
-  QualType ToType = QualType::getFromOpaquePtr(ToTypePtr);
+  QualType FromType = getFromType();
+  QualType ToType = getToType();
 
   // Note that FromType has not necessarily been transformed by the
   // array-to-pointer implicit conversion, so check for its presence
@@ -250,6 +247,9 @@
   case EllipsisConversion:
     fprintf(stderr, "Ellipsis conversion");
     break;
+  case AmbiguousConversion:
+    fprintf(stderr, "Ambiguous conversion");
+    break;
   case BadConversion:
     fprintf(stderr, "Bad conversion");
     break;
@@ -258,6 +258,22 @@
   fprintf(stderr, "\n");
 }
 
+void AmbiguousConversionSequence::construct() {
+  new (&conversions()) ConversionSet();
+}
+
+void AmbiguousConversionSequence::destruct() {
+  conversions().~ConversionSet();
+}
+
+void
+AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
+  FromTypePtr = O.FromTypePtr;
+  ToTypePtr = O.ToTypePtr;
+  new (&conversions()) ConversionSet(O.conversions());
+}
+
+
 // IsOverload - Determine whether the given New declaration is an
 // overload of the declarations in Old. This routine returns false if
 // New and Old cannot be overloaded, e.g., if New has the same
@@ -432,14 +448,14 @@
   OverloadCandidateSet Conversions;
   OverloadingResult UserDefResult = OR_Success;
   if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard))
-    ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+    ICS.setStandard();
   else if (getLangOptions().CPlusPlus &&
            (UserDefResult = IsUserDefinedConversion(From, ToType, 
                                    ICS.UserDefined,
                                    Conversions,
                                    !SuppressUserConversions, AllowExplicit,
 				   ForceRValue, UserCast)) == OR_Success) {
-    ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
+    ICS.setUserDefined();
     // C++ [over.ics.user]p4:
     //   A conversion of an expression of class type to the same class
     //   type is given Exact Match rank, and a conversion of an
@@ -456,10 +472,10 @@
           (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) {
         // Turn this into a "standard" conversion sequence, so that it
         // gets ranked with standard conversion sequences.
-        ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+        ICS.setStandard();
         ICS.Standard.setAsIdentityConversion();
-        ICS.Standard.FromTypePtr = From->getType().getAsOpaquePtr();
-        ICS.Standard.ToTypePtr = ToType.getAsOpaquePtr();
+        ICS.Standard.setFromType(From->getType());
+        ICS.Standard.setToType(ToType);
         ICS.Standard.CopyConstructor = Constructor;
         if (ToCanon != FromCanon)
           ICS.Standard.Second = ICK_Derived_To_Base;
@@ -473,17 +489,18 @@
     //   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.ConversionKind == ImplicitConversionSequence::UserDefinedConversion)
-      ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+    if (SuppressUserConversions && ICS.isUserDefined())
+      ICS.setBad();
+  } else if (UserDefResult == OR_Ambiguous) {
+    ICS.setAmbiguous();
+    ICS.Ambiguous.setFromType(From->getType());
+    ICS.Ambiguous.setToType(ToType);
+    for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+         Cand != Conversions.end(); ++Cand)
+      if (Cand->Viable)
+        ICS.Ambiguous.addConversion(Cand->Function);
   } else {
-    ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
-    if (UserDefResult == OR_Ambiguous) {
-      for (OverloadCandidateSet::iterator Cand = Conversions.begin();
-           Cand != Conversions.end(); ++Cand)
-        if (Cand->Viable)
-          ICS.ConversionFunctionSet.push_back(Cand->Function);
-    }
+    ICS.setBad();
   }
 
   return ICS;
@@ -524,7 +541,7 @@
   SCS.setAsIdentityConversion();
   SCS.Deprecated = false;
   SCS.IncompatibleObjC = false;
-  SCS.FromTypePtr = FromType.getAsOpaquePtr();
+  SCS.setFromType(FromType);
   SCS.CopyConstructor = 0;
 
   // There are no standard conversions for class types in C++, so
@@ -573,7 +590,7 @@
       // conversion (4.4). (C++ 4.2p2)
       SCS.Second = ICK_Identity;
       SCS.Third = ICK_Qualification;
-      SCS.ToTypePtr = ToType.getAsOpaquePtr();
+      SCS.setToType(ToType);
       return true;
     }
   } else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) {
@@ -724,7 +741,7 @@
   if (CanonFrom != CanonTo)
     return false;
 
-  SCS.ToTypePtr = FromType.getAsOpaquePtr();
+  SCS.setToType(FromType);
   return true;
 }
 
@@ -1544,8 +1561,7 @@
         //   the argument of the constructor.
         //
         QualType ThisType = Constructor->getThisType(Context);
-        if (Best->Conversions[0].ConversionKind == 
-            ImplicitConversionSequence::EllipsisConversion)
+        if (Best->Conversions[0].isEllipsis())
           User.EllipsisConversion = true;
         else {
           User.Before = Best->Conversions[0].Standard;
@@ -1553,9 +1569,9 @@
         }
         User.ConversionFunction = Constructor;
         User.After.setAsIdentityConversion();
-        User.After.FromTypePtr
-          = ThisType->getAs<PointerType>()->getPointeeType().getAsOpaquePtr();
-        User.After.ToTypePtr = ToType.getAsOpaquePtr();
+        User.After.setFromType(
+          ThisType->getAs<PointerType>()->getPointeeType());
+        User.After.setToType(ToType);
         return OR_Success;
       } else if (CXXConversionDecl *Conversion
                    = dyn_cast<CXXConversionDecl>(Best->Function)) {
@@ -1635,18 +1651,28 @@
   //      conversion sequence than an ellipsis conversion sequence
   //      (13.3.3.1.3).
   //
-  if (ICS1.ConversionKind < ICS2.ConversionKind)
-    return ImplicitConversionSequence::Better;
-  else if (ICS2.ConversionKind < ICS1.ConversionKind)
-    return ImplicitConversionSequence::Worse;
+  // C++0x [over.best.ics]p10:
+  //   For the purpose of ranking implicit conversion sequences as
+  //   described in 13.3.3.2, the ambiguous conversion sequence is
+  //   treated as a user-defined sequence that is indistinguishable
+  //   from any other user-defined conversion sequence.
+  if (ICS1.getKind() < ICS2.getKind()) {
+    if (!(ICS1.isUserDefined() && ICS2.isAmbiguous()))
+      return ImplicitConversionSequence::Better;
+  } else if (ICS2.getKind() < ICS1.getKind()) {
+    if (!(ICS2.isUserDefined() && ICS1.isAmbiguous()))
+      return ImplicitConversionSequence::Worse;
+  }
+
+  if (ICS1.isAmbiguous() || ICS2.isAmbiguous())
+    return ImplicitConversionSequence::Indistinguishable;
 
   // Two implicit conversion sequences of the same form are
   // indistinguishable conversion sequences unless one of the
   // following rules apply: (C++ 13.3.3.2p3):
-  if (ICS1.ConversionKind == ImplicitConversionSequence::StandardConversion)
+  if (ICS1.isStandard())
     return CompareStandardConversionSequences(ICS1.Standard, ICS2.Standard);
-  else if (ICS1.ConversionKind ==
-             ImplicitConversionSequence::UserDefinedConversion) {
+  else if (ICS1.isUserDefined()) {
     // User-defined conversion sequence U1 is a better conversion
     // sequence than another user-defined conversion sequence U2 if
     // they contain the same user-defined conversion function or
@@ -1739,8 +1765,8 @@
     // Both conversion sequences are conversions to void
     // pointers. Compare the source types to determine if there's an
     // inheritance relationship in their sources.
-    QualType FromType1 = QualType::getFromOpaquePtr(SCS1.FromTypePtr);
-    QualType FromType2 = QualType::getFromOpaquePtr(SCS2.FromTypePtr);
+    QualType FromType1 = SCS1.getFromType();
+    QualType FromType2 = SCS2.getFromType();
 
     // Adjust the types we're converting from via the array-to-pointer
     // conversion, if we need to.
@@ -1796,8 +1822,8 @@
     //      top-level cv-qualifiers, and the type to which the reference
     //      initialized by S2 refers is more cv-qualified than the type
     //      to which the reference initialized by S1 refers.
-    QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
-    QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+    QualType T1 = SCS1.getToType();
+    QualType T2 = SCS2.getToType();
     T1 = Context.getCanonicalType(T1);
     T2 = Context.getCanonicalType(T2);
     Qualifiers T1Quals, T2Quals;
@@ -1927,10 +1953,10 @@
 ImplicitConversionSequence::CompareKind
 Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
                                       const StandardConversionSequence& SCS2) {
-  QualType FromType1 = QualType::getFromOpaquePtr(SCS1.FromTypePtr);
-  QualType ToType1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
-  QualType FromType2 = QualType::getFromOpaquePtr(SCS2.FromTypePtr);
-  QualType ToType2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+  QualType FromType1 = SCS1.getFromType();
+  QualType ToType1 = SCS1.getToType();
+  QualType FromType2 = SCS2.getFromType();
+  QualType ToType2 = SCS2.getToType();
 
   // Adjust the types we're converting from via the array-to-pointer
   // conversion, if we need to.
@@ -2175,7 +2201,7 @@
   // to exit early.
   ImplicitConversionSequence ICS;
   ICS.Standard.setAsIdentityConversion();
-  ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+  ICS.setBad();
 
   // We need to have an object of class type.
   if (const PointerType *PT = FromType->getAs<PointerType>())
@@ -2211,9 +2237,9 @@
     return ICS;
 
   // Success. Mark this as a reference binding.
-  ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
-  ICS.Standard.FromTypePtr = FromType.getAsOpaquePtr();
-  ICS.Standard.ToTypePtr = ImplicitParamType.getAsOpaquePtr();
+  ICS.setStandard();
+  ICS.Standard.setFromType(FromType);
+  ICS.Standard.setToType(ImplicitParamType);
   ICS.Standard.ReferenceBinding = true;
   ICS.Standard.DirectBinding = true;
   ICS.Standard.RRefBinding = false;
@@ -2242,7 +2268,7 @@
   ImplicitConversionSequence ICS
     = TryObjectArgumentInitialization(From->getType(), Method,
                                       Method->getParent());
-  if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
+  if (ICS.isBad())
     return Diag(From->getSourceRange().getBegin(),
                 diag::err_implicit_object_parameter_init)
        << ImplicitParamRecordType << FromRecordType << From->getSourceRange();
@@ -2274,8 +2300,8 @@
 /// of the expression From to bool (C++0x [conv]p3).
 bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
   ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From);
-  if (!PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting))
-    return false;
+  if (!ICS.isBad())
+    return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
   
   if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
     return  Diag(From->getSourceRange().getBegin(),
@@ -2388,35 +2414,15 @@
         = TryCopyInitialization(Args[ArgIdx], ParamType,
                                 SuppressUserConversions, ForceRValue,
                                 /*InOverloadResolution=*/true);
-      if (Candidate.Conversions[ArgIdx].ConversionKind
-            == ImplicitConversionSequence::BadConversion) {
-      // 13.3.3.1-p10 If several different sequences of conversions exist that 
-      // each convert the argument to the parameter type, the implicit conversion 
-      // sequence associated with the parameter is defined to be the unique conversion 
-      // sequence designated the ambiguous conversion sequence. For the purpose of 
-      // ranking implicit conversion sequences as described in 13.3.3.2, the ambiguous 
-      // conversion sequence is treated as a user-defined sequence that is 
-      // indistinguishable from any other user-defined conversion sequence
-        if (!Candidate.Conversions[ArgIdx].ConversionFunctionSet.empty()) {
-          Candidate.Conversions[ArgIdx].ConversionKind =
-            ImplicitConversionSequence::UserDefinedConversion;
-          // Set the conversion function to one of them. As due to ambiguity,
-          // they carry the same weight and is needed for overload resolution
-          // later.
-          Candidate.Conversions[ArgIdx].UserDefined.ConversionFunction =
-            Candidate.Conversions[ArgIdx].ConversionFunctionSet[0];
-        }
-        else {
-          Candidate.Viable = false;
-          break;
-        }
+      if (Candidate.Conversions[ArgIdx].isBad()) {
+        Candidate.Viable = false;
+        break;
       }
     } else {
       // (C++ 13.3.2p2): For the purposes of overload resolution, any
       // argument for which there is no corresponding parameter is
       // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
-      Candidate.Conversions[ArgIdx].ConversionKind
-        = ImplicitConversionSequence::EllipsisConversion;
+      Candidate.Conversions[ArgIdx].setEllipsis();
     }
   }
 }
@@ -2552,8 +2558,7 @@
     // parameter.
     Candidate.Conversions[0]
       = TryObjectArgumentInitialization(ObjectType, Method, ActingContext);
-    if (Candidate.Conversions[0].ConversionKind
-          == ImplicitConversionSequence::BadConversion) {
+    if (Candidate.Conversions[0].isBad()) {
       Candidate.Viable = false;
       return;
     }
@@ -2572,8 +2577,7 @@
         = TryCopyInitialization(Args[ArgIdx], ParamType,
                                 SuppressUserConversions, ForceRValue,
                                 /*InOverloadResolution=*/true);
-      if (Candidate.Conversions[ArgIdx + 1].ConversionKind
-            == ImplicitConversionSequence::BadConversion) {
+      if (Candidate.Conversions[ArgIdx + 1].isBad()) {
         Candidate.Viable = false;
         break;
       }
@@ -2581,8 +2585,7 @@
       // (C++ 13.3.2p2): For the purposes of overload resolution, any
       // argument for which there is no corresponding parameter is
       // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
-      Candidate.Conversions[ArgIdx + 1].ConversionKind
-        = ImplicitConversionSequence::EllipsisConversion;
+      Candidate.Conversions[ArgIdx + 1].setEllipsis();
     }
   }
 }
@@ -2706,9 +2709,8 @@
   Candidate.IsSurrogate = false;
   Candidate.IgnoreObjectArgument = false;
   Candidate.FinalConversion.setAsIdentityConversion();
-  Candidate.FinalConversion.FromTypePtr
-    = Conversion->getConversionType().getAsOpaquePtr();
-  Candidate.FinalConversion.ToTypePtr = ToType.getAsOpaquePtr();
+  Candidate.FinalConversion.setFromType(Conversion->getConversionType());
+  Candidate.FinalConversion.setToType(ToType);
 
   // Determine the implicit conversion sequence for the implicit
   // object parameter.
@@ -2722,8 +2724,7 @@
   // in overload resolution. 
   if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base)
     Candidate.Conversions[0].Standard.Second = ICK_Identity;
-  if (Candidate.Conversions[0].ConversionKind
-      == ImplicitConversionSequence::BadConversion) {
+  if (Candidate.Conversions[0].isBad()) {
     Candidate.Viable = false;
     return;
   }
@@ -2766,7 +2767,7 @@
                           /*ForceRValue=*/false,
                           /*InOverloadResolution=*/false);
 
-  switch (ICS.ConversionKind) {
+  switch (ICS.getKind()) {
   case ImplicitConversionSequence::StandardConversion:
     Candidate.FinalConversion = ICS.Standard;
     break;
@@ -2844,7 +2845,7 @@
   // object parameter.
   ImplicitConversionSequence ObjectInit
     = TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
-  if (ObjectInit.ConversionKind == ImplicitConversionSequence::BadConversion) {
+  if (ObjectInit.isBad()) {
     Candidate.Viable = false;
     return;
   }
@@ -2852,8 +2853,7 @@
   // The first conversion is actually a user-defined conversion whose
   // first conversion is ObjectInit's standard conversion (which is
   // effectively a reference binding). Record it as such.
-  Candidate.Conversions[0].ConversionKind
-    = ImplicitConversionSequence::UserDefinedConversion;
+  Candidate.Conversions[0].setUserDefined();
   Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
   Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
   Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
@@ -2894,8 +2894,7 @@
                                 /*SuppressUserConversions=*/false,
                                 /*ForceRValue=*/false,
                                 /*InOverloadResolution=*/false);
-      if (Candidate.Conversions[ArgIdx + 1].ConversionKind
-            == ImplicitConversionSequence::BadConversion) {
+      if (Candidate.Conversions[ArgIdx + 1].isBad()) {
         Candidate.Viable = false;
         break;
       }
@@ -2903,8 +2902,7 @@
       // (C++ 13.3.2p2): For the purposes of overload resolution, any
       // argument for which there is no corresponding parameter is
       // considered to ""match the ellipsis" (C+ 13.3.3.1.3).
-      Candidate.Conversions[ArgIdx + 1].ConversionKind
-        = ImplicitConversionSequence::EllipsisConversion;
+      Candidate.Conversions[ArgIdx + 1].setEllipsis();
     }
   }
 }
@@ -3038,8 +3036,7 @@
                                 /*ForceRValue=*/false,
                                 /*InOverloadResolution=*/false);
     }
-    if (Candidate.Conversions[ArgIdx].ConversionKind
-        == ImplicitConversionSequence::BadConversion) {
+    if (Candidate.Conversions[ArgIdx].isBad()) {
       Candidate.Viable = false;
       break;
     }
@@ -4304,11 +4301,22 @@
   Diag(Fn->getLocation(), diag::note_ovl_candidate);
 }
 
-namespace {
-
-void NoteDeletedCandidate(Sema &S, OverloadCandidate *Cand) {
+/// Diagnoses an ambiguous conversion.  The partial diagnostic is the
+/// "lead" diagnostic; it will be given two arguments, the source and
+/// target types of the conversion.
+void Sema::DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
+                                       SourceLocation CaretLoc,
+                                       const PartialDiagnostic &PDiag) {
+  Diag(CaretLoc, PDiag)
+    << ICS.Ambiguous.getFromType() << ICS.Ambiguous.getToType();
+  for (AmbiguousConversionSequence::const_iterator
+         I = ICS.Ambiguous.begin(), E = ICS.Ambiguous.end(); I != E; ++I) {
+    NoteOverloadCandidate(*I);
+  }
 }
 
+namespace {
+
 void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
   // Note deleted candidates, but only if they're viable.
   if (Cand->Viable &&
@@ -4335,18 +4343,13 @@
     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)
+
+      if (!Conversion.isAmbiguous())
         continue;
-      S.Diag(Cand->Function->getLocation(), 
-             diag::note_ovl_candidate_not_viable) << (i+1);
+
+      S.DiagnoseAmbiguousConversion(Conversion, Cand->Function->getLocation(),
+                         PDiag(diag::note_ovl_candidate_not_viable) << (i+1));
       errReported = true;
-      for (int j = Conversion.ConversionFunctionSet.size()-1; 
-           j >= 0; j--) {
-        FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
-        S.NoteOverloadCandidate(Func);
-      }
     }
   }
 
@@ -4411,21 +4414,11 @@
   unsigned NoOperands = Cand->Conversions.size();
   for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
     const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
-    if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion ||
-        ICS.ConversionFunctionSet.empty())
-      continue;
-    if (CXXConversionDecl *Func = dyn_cast<CXXConversionDecl>(
-                     Cand->Conversions[ArgIdx].ConversionFunctionSet[0])) {
-      QualType FromTy = 
-        QualType(static_cast<Type*>(ICS.UserDefined.Before.FromTypePtr),0);
-      S.Diag(OpLoc, diag::note_ambiguous_type_conversion)
-        << FromTy << Func->getConversionType();
-    }
-    for (unsigned j = 0; j < ICS.ConversionFunctionSet.size(); j++) {
-      FunctionDecl *Func = 
-        Cand->Conversions[ArgIdx].ConversionFunctionSet[j];
-      S.NoteOverloadCandidate(Func);
-    }
+    if (ICS.isBad()) break; // all meaningless after first invalid
+    if (!ICS.isAmbiguous()) continue;
+
+    S.DiagnoseAmbiguousConversion(ICS, OpLoc,
+                              PDiag(diag::note_ambiguous_type_conversion));
   }
 }
 
@@ -4479,7 +4472,7 @@
       Cands.push_back(Cand);
   std::sort(Cands.begin(), Cands.end(), CompareOverloadCandidates(SourceMgr));
   
-  bool ReportedNonViableOperator = false;
+  bool ReportedAmbiguousConversions = false;
 
   llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
   for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
@@ -4492,16 +4485,20 @@
 
     // This a builtin candidate.  We do not, in general, want to list
     // every possible builtin candidate.
+    else if (Cand->Viable) {
+      // Generally we only see ambiguities including viable builtin
+      // operators if overload resolution got screwed up by an
+      // ambiguous user-defined conversion.
+      //
+      // FIXME: It's quite possible for different conversions to see
+      // different ambiguities, though.
+      if (!ReportedAmbiguousConversions) {
+        NoteAmbiguousUserConversions(*this, OpLoc, Cand);
+        ReportedAmbiguousConversions = true;
+      }
 
-    // If this is a viable builtin, print it.
-    else if (Cand->Viable)
+      // If this is a viable builtin, print it.
       NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
-
-    // Otherwise, non-viability might be due to ambiguous user-defined
-    // conversions.  Report them exactly once.
-    else if (!ReportedNonViableOperator) {
-      NoteAmbiguousUserConversions(*this, OpLoc, Cand);
-      ReportedNonViableOperator = true;
     }
   }
 }
@@ -5414,7 +5411,7 @@
         << Args[0]->getSourceRange() << Args[1]->getSourceRange();
       PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
       return ExprError();
-    }
+  }
 
   // We matched a built-in operator; build it.
   return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Mon Jan 11 18:44:57 2010
@@ -149,6 +149,15 @@
     /// conversions.
     CXXConstructorDecl *CopyConstructor;
 
+    void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+    void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+    QualType getFromType() const {
+      return QualType::getFromOpaquePtr(FromTypePtr);
+    }
+    QualType getToType() const {
+      return QualType::getFromOpaquePtr(ToTypePtr);
+    }
+
     void setAsIdentityConversion();
     ImplicitConversionRank getRank() const;
     bool isPointerConversionToBool() const;
@@ -190,6 +199,48 @@
     void DebugPrint() const;
   };
 
+  /// Represents an ambiguous user-defined conversion sequence.
+  struct AmbiguousConversionSequence {
+    typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet;
+
+    void *FromTypePtr;
+    void *ToTypePtr;
+    char Buffer[sizeof(ConversionSet)];
+
+    QualType getFromType() const {
+      return QualType::getFromOpaquePtr(FromTypePtr);
+    }
+    QualType getToType() const {
+      return QualType::getFromOpaquePtr(ToTypePtr);
+    }
+    void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+    void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+
+    ConversionSet &conversions() {
+      return *reinterpret_cast<ConversionSet*>(Buffer);
+    }
+
+    const ConversionSet &conversions() const {
+      return *reinterpret_cast<const ConversionSet*>(Buffer);
+    }
+
+    void addConversion(FunctionDecl *D) {
+      conversions().push_back(D);
+    }
+
+    typedef ConversionSet::iterator iterator;
+    iterator begin() { return conversions().begin(); }
+    iterator end() { return conversions().end(); }
+
+    typedef ConversionSet::const_iterator const_iterator;
+    const_iterator begin() const { return conversions().begin(); }
+    const_iterator end() const { return conversions().end(); }
+
+    void construct();
+    void destruct();
+    void copyFrom(const AmbiguousConversionSequence &);
+  };
+
   /// 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),
@@ -197,18 +248,26 @@
   struct ImplicitConversionSequence {
     /// Kind - The kind of implicit conversion sequence. BadConversion
     /// specifies that there is no conversion from the source type to
-    /// the target type. The enumerator values are ordered such that
-    /// better implicit conversions have smaller values.
+    /// the target type.  AmbiguousConversion represents the unique
+    /// ambiguous conversion (C++0x [over.best.ics]p10).
     enum Kind {
       StandardConversion = 0,
       UserDefinedConversion,
+      AmbiguousConversion,
       EllipsisConversion,
       BadConversion
     };
 
+  private:
     /// ConversionKind - The kind of implicit conversion sequence.
     Kind ConversionKind;
 
+    void setKind(Kind K) {
+      if (isAmbiguous()) Ambiguous.destruct();
+      ConversionKind = K;
+    }
+
+  public:
     union {
       /// When ConversionKind == StandardConversion, provides the
       /// details of the standard conversion sequence.
@@ -217,12 +276,54 @@
       /// When ConversionKind == UserDefinedConversion, provides the
       /// details of the user-defined conversion sequence.
       UserDefinedConversionSequence UserDefined;
+
+      /// When ConversionKind == AmbiguousConversion, provides the
+      /// details of the ambiguous conversion.
+      AmbiguousConversionSequence Ambiguous;
     };
+
+    ImplicitConversionSequence() : ConversionKind(BadConversion) {}
+    ~ImplicitConversionSequence() {
+      if (isAmbiguous()) Ambiguous.destruct();
+    }
+    ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+      : ConversionKind(Other.ConversionKind)
+    {
+      switch (ConversionKind) {
+      case StandardConversion: Standard = Other.Standard; break;
+      case UserDefinedConversion: UserDefined = Other.UserDefined; break;
+      case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
+      case EllipsisConversion: break;
+      case BadConversion: break;
+      }
+    }
+
+    ImplicitConversionSequence &
+        operator=(const ImplicitConversionSequence &Other) {
+      if (isAmbiguous()) Ambiguous.destruct();
+      new (this) ImplicitConversionSequence(Other);
+      return *this;
+    }
     
-    /// When ConversionKind == BadConversion due to multiple conversion
-    /// functions, this will list those functions.
-    llvm::SmallVector<FunctionDecl*, 4> ConversionFunctionSet;
-    
+    Kind getKind() const { return ConversionKind; }
+    bool isBad() const { return ConversionKind == BadConversion; }
+    bool isStandard() const { return ConversionKind == StandardConversion; }
+    bool isEllipsis() const { return ConversionKind == EllipsisConversion; }
+    bool isAmbiguous() const { return ConversionKind == AmbiguousConversion; }
+    bool isUserDefined() const {
+      return ConversionKind == UserDefinedConversion;
+    }
+
+    void setBad() { setKind(BadConversion); }
+    void setStandard() { setKind(StandardConversion); }
+    void setEllipsis() { setKind(EllipsisConversion); }
+    void setUserDefined() { setKind(UserDefinedConversion); }
+    void setAmbiguous() {
+      if (isAmbiguous()) return;
+      ConversionKind = AmbiguousConversion;
+      Ambiguous.construct();
+    }
+
     // The result of a comparison between implicit conversion
     // sequences. Use Sema::CompareImplicitConversionSequences to
     // actually perform the comparison.
@@ -280,6 +381,16 @@
     /// after the call to the overload candidate to convert the result
     /// of calling the conversion function to the required type.
     StandardConversionSequence FinalConversion;
+
+    /// hasAmbiguousConversion - Returns whether this overload
+    /// candidate requires an ambiguous conversion or not.
+    bool hasAmbiguousConversion() const {
+      for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator
+             I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
+        if (I->isAmbiguous()) return true;
+      }
+      return false;
+    }
   };
 
   /// OverloadCandidateSet - A set of overload candidates, used in C++

Modified: cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp?rev=93214&r1=93213&r2=93214&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp (original)
+++ cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp Mon Jan 11 18:44:57 2010
@@ -21,6 +21,13 @@
     func(b1, f()); // expected-error {{call to 'func' is ambiguous}}
     return f(); // expected-error {{conversion from 'struct test0::B' to 'int const' is ambiguous}}
   }
+
+  // This used to crash when comparing the two operands.
+  void func2(const char cc); // expected-note {{candidate function}}
+  void func2(const int ci); // expected-note {{candidate function}}
+  void Test2() {
+    func2(b1); // expected-error {{call to 'func2' is ambiguous}}
+  }
 }
 
 namespace test1 {

Modified: cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp?rev=93214&r1=93213&r2=93214&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp (original)
+++ cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp Mon Jan 11 18:44:57 2010
@@ -40,7 +40,7 @@
 }
 
 void foo1(C1 c1, int E::* pmf) {
-        // FIXME. Error reporting needs much improvement here.
-        int i = c1->*pmf;	// expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct C1'}} \
-                                // expected-note {{because of ambiguity in conversion of 'struct C1' to 'struct E *'}}
+        int i = c1->*pmf;	// expected-error {{use of overloaded operator '->*' is ambiguous}} \
+                                // expected-note {{because of ambiguity in conversion of 'struct C1' to 'struct E *'}} \
+                                // expected-note 4 {{built-in candidate operator}}
 }

Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=93214&r1=93213&r2=93214&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Mon Jan 11 18:44:57 2010
@@ -7,8 +7,8 @@
 struct ToBool { explicit operator bool(); };
 
 struct B;
-struct A { A(); A(const B&); };
-struct B { operator A() const; };
+struct A { A(); A(const B&); }; // expected-note 2 {{candidate constructor}}
+struct B { operator A() const; }; // expected-note 2 {{candidate function}}
 struct I { operator int(); };
 struct J { operator I(); };
 struct K { operator double(); };
@@ -50,8 +50,8 @@
 enum Enum { EVal };
 
 struct Ambig {
-  operator short();
-  operator signed char();
+  operator short(); // expected-note 2 {{candidate function}}
+  operator signed char(); // expected-note 2 {{candidate function}}
 };
 
 void test()
@@ -129,10 +129,10 @@
   vfn pfn = i1 ? F() : test;
   pfn = i1 ? test : F();
   // these are ambiguous - better messages would be nice
-  (void)(i1 ? A() : B()); // expected-error {{incompatible operand types}}
-  (void)(i1 ? B() : A()); // expected-error {{incompatible operand types}}
-  (void)(i1 ? 1 : Ambig()); // expected-error {{incompatible operand types}}
-  (void)(i1 ? Ambig() : 1); // expected-error {{incompatible operand types}}
+  (void)(i1 ? A() : B()); // expected-error {{conversion from 'struct B' to 'struct A' is ambiguous}}
+  (void)(i1 ? B() : A()); // expected-error {{conversion from 'struct B' to 'struct A' is ambiguous}}
+  (void)(i1 ? 1 : Ambig()); // expected-error {{conversion from 'struct Ambig' to 'int' is ambiguous}}
+  (void)(i1 ? Ambig() : 1); // expected-error {{conversion from 'struct Ambig' to 'int' is ambiguous}}
   // By the way, this isn't an lvalue:
   &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}}
 





More information about the cfe-commits mailing list