[cfe-commits] r118178 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaCXX/overloaded-builtin-operators.cpp

Douglas Gregor dgregor at apple.com
Wed Nov 3 10:00:07 PDT 2010


Author: dgregor
Date: Wed Nov  3 12:00:07 2010
New Revision: 118178

URL: http://llvm.org/viewvc/llvm-project?rev=118178&view=rev
Log:
When producing overload candidates for binary built-in operators, keep
the sets of available conversions for the first and second arguments
separate. This is apparently the indent of C++ [over.built], and
reduces the number of overload candidates generated, eliminating some
ambiguities. Fixes PR8477.

Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=118178&r1=118177&r2=118178&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Nov  3 12:00:07 2010
@@ -4541,15 +4541,17 @@
   for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
     VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]);
   
-  BuiltinCandidateTypeSet CandidateTypes(*this);
-  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)
-    CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(),
-                                         OpLoc,
-                                         true,
-                                         (Op == OO_Exclaim ||
-                                          Op == OO_AmpAmp ||
-                                          Op == OO_PipePipe),
-                                         VisibleTypeConversionsQuals);
+  llvm::SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes;
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    CandidateTypes.push_back(BuiltinCandidateTypeSet(*this));
+    CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(),
+                                                 OpLoc,
+                                                 true,
+                                                 (Op == OO_Exclaim ||
+                                                  Op == OO_AmpAmp ||
+                                                  Op == OO_PipePipe),
+                                                 VisibleTypeConversionsQuals);
+  }
 
   // C++ [over.built]p1:
   //   If there is a user-written candidate with the same name and parameter
@@ -4563,29 +4565,35 @@
   llvm::DenseSet<std::pair<CanQualType, CanQualType> > 
     UserDefinedBinaryOperators;
   
-  if (CandidateTypes.enumeration_begin() != CandidateTypes.enumeration_end()) {
-    for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
-                                     CEnd = CandidateSet.end();
-         C != CEnd; ++C) {
-      if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
-        continue;
-      
-      // Check if the first parameter is of enumeration type.
-      QualType FirstParamType
-        = C->Function->getParamDecl(0)->getType().getUnqualifiedType();
-      if (!FirstParamType->isEnumeralType())
-        continue;
-      
-      // Check if the second parameter is of enumeration type.
-      QualType SecondParamType
-        = C->Function->getParamDecl(1)->getType().getUnqualifiedType();
-      if (!SecondParamType->isEnumeralType())
-        continue;
+  /// Set of (canonical) types that we've already handled.
+  llvm::SmallPtrSet<QualType, 8> AddedTypes;
+  
+  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+    if (CandidateTypes[ArgIdx].enumeration_begin() 
+                                != CandidateTypes[ArgIdx].enumeration_end()) {
+      for (OverloadCandidateSet::iterator C = CandidateSet.begin(),
+                                       CEnd = CandidateSet.end();
+           C != CEnd; ++C) {
+        if (!C->Viable || !C->Function || C->Function->getNumParams() != 2)
+          continue;
+        
+        // Check if the first parameter is of enumeration type.
+        QualType FirstParamType
+          = C->Function->getParamDecl(0)->getType().getUnqualifiedType();
+        if (!FirstParamType->isEnumeralType())
+          continue;
+        
+        // Check if the second parameter is of enumeration type.
+        QualType SecondParamType
+          = C->Function->getParamDecl(1)->getType().getUnqualifiedType();
+        if (!SecondParamType->isEnumeralType())
+          continue;
 
-      // Add this operator to the set of known user-defined operators.
-      UserDefinedBinaryOperators.insert(
-                  std::make_pair(Context.getCanonicalType(FirstParamType),
-                                 Context.getCanonicalType(SecondParamType)));
+        // Add this operator to the set of known user-defined operators.
+        UserDefinedBinaryOperators.insert(
+                    std::make_pair(Context.getCanonicalType(FirstParamType),
+                                   Context.getCanonicalType(SecondParamType)));
+      }
     }
   }
   
@@ -4676,8 +4684,10 @@
     //       T*VQ&      operator--(T*VQ&);
     //       T*         operator++(T*VQ&, int);
     //       T*         operator--(T*VQ&, int);
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
-         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+    for (BuiltinCandidateTypeSet::iterator 
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
       // Skip pointer types that aren't pointers to object types.
       if (!(*Ptr)->getPointeeType()->isIncompleteOrObjectType())
         continue;
@@ -4716,8 +4726,10 @@
     //   For every function type T, there exist candidate operator
     //   functions of the form
     //       T&         operator*(T*);
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
-         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+    for (BuiltinCandidateTypeSet::iterator 
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
       QualType ParamTy = *Ptr;
       QualType PointeeTy = ParamTy->getPointeeType();
       AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy),
@@ -4731,8 +4743,10 @@
     //   the form
     //
     //       T*         operator+(T*);
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
-         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+    for (BuiltinCandidateTypeSet::iterator 
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
       QualType ParamTy = *Ptr;
       AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet);
     }
@@ -4753,8 +4767,9 @@
     }
       
     // Extension: We also add these operators for vector types.
-    for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(),
-                                        VecEnd = CandidateTypes.vector_end(); 
+    for (BuiltinCandidateTypeSet::iterator
+              Vec = CandidateTypes[0].vector_begin(),
+           VecEnd = CandidateTypes[0].vector_end(); 
          Vec != VecEnd; ++Vec) {
       QualType VecTy = *Vec;
       AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
@@ -4774,8 +4789,9 @@
     }
       
     // Extension: We also add this operator for vector types.
-    for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(),
-                                        VecEnd = CandidateTypes.vector_end(); 
+    for (BuiltinCandidateTypeSet::iterator
+              Vec = CandidateTypes[0].vector_begin(),
+           VecEnd = CandidateTypes[0].vector_end(); 
          Vec != VecEnd; ++Vec) {
       QualType VecTy = *Vec;
       AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet);
@@ -4806,15 +4822,22 @@
     //
     //        bool operator==(T,T);
     //        bool operator!=(T,T);
-    for (BuiltinCandidateTypeSet::iterator
-           MemPtr = CandidateTypes.member_pointer_begin(),
-           MemPtrEnd = CandidateTypes.member_pointer_end();
-         MemPtr != MemPtrEnd;
-         ++MemPtr) {
-      QualType ParamTypes[2] = { *MemPtr, *MemPtr };
-      AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+           MemPtr != MemPtrEnd;
+           ++MemPtr) {
+        // Don't add the same builtin candidate twice.
+        if (!AddedTypes.insert(Context.getCanonicalType(*MemPtr)))
+          continue;
+        
+        QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+        AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+      }
     }
-
+    AddedTypes.clear();
+    
     // Fall through
 
   case OO_Less:
@@ -4832,21 +4855,35 @@
     //        bool       operator>=(T, T);
     //        bool       operator==(T, T);
     //        bool       operator!=(T, T);
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
-         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
-      QualType ParamTypes[2] = { *Ptr, *Ptr };
-      AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
-    }
-    for (BuiltinCandidateTypeSet::iterator Enum
-           = CandidateTypes.enumeration_begin();
-         Enum != CandidateTypes.enumeration_end(); ++Enum) {
-      QualType ParamTypes[2] = { *Enum, *Enum };
-      CanQualType CanonType = Context.getCanonicalType(*Enum);
-      if (!UserDefinedBinaryOperators.count(
-                                          std::make_pair(CanonType, CanonType)))
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator 
+                Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+             PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        // Don't add the same builtin candidate twice.
+        if (!AddedTypes.insert(Context.getCanonicalType(*Ptr)))
+          continue;
+        
+        QualType ParamTypes[2] = { *Ptr, *Ptr };
         AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+      }
+      for (BuiltinCandidateTypeSet::iterator 
+                Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+             EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+           Enum != EnumEnd; ++Enum) {
+        // Don't add the same builtin candidate twice.
+        if (!AddedTypes.insert(Context.getCanonicalType(*Enum)))
+          continue;
+        
+        QualType ParamTypes[2] = { *Enum, *Enum };
+        CanQualType CanonType = Context.getCanonicalType(*Enum);
+        if (!UserDefinedBinaryOperators.count(
+                                            std::make_pair(CanonType, CanonType)))
+          AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet);
+      }
     }
-
+    AddedTypes.clear();
+      
     // Fall through.
     isComparison = true;
 
@@ -4872,26 +4909,46 @@
       //   exist candidate operator functions of the form
       //
       //      ptrdiff_t  operator-(T, T);
-      for (BuiltinCandidateTypeSet::iterator Ptr
-             = CandidateTypes.pointer_begin();
-           Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      for (BuiltinCandidateTypeSet::iterator 
+                Ptr = CandidateTypes[0].pointer_begin(),
+             PtrEnd = CandidateTypes[0].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
         QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
 
         // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t)
         AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
 
+        if (Op == OO_Minus) {
+          // ptrdiff_t operator-(T, T);
+          if (!AddedTypes.insert(Context.getCanonicalType(*Ptr)))
+            continue;
+          
+          ParamTypes[1] = *Ptr;
+          AddBuiltinCandidate(Context.getPointerDiffType(), ParamTypes,
+                              Args, 2, CandidateSet);
+        }
+      }
+      
+      for (BuiltinCandidateTypeSet::iterator 
+                Ptr = CandidateTypes[1].pointer_begin(),
+             PtrEnd = CandidateTypes[1].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
         if (Op == OO_Plus) {
           // T* operator+(ptrdiff_t, T*);
-          ParamTypes[0] = ParamTypes[1];
-          ParamTypes[1] = *Ptr;
+          QualType ParamTypes[2] = { Context.getPointerDiffType(), *Ptr };
           AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
         } else {
           // ptrdiff_t operator-(T, T);
-          ParamTypes[1] = *Ptr;
+          if (!AddedTypes.insert(Context.getCanonicalType(*Ptr)))
+            continue;
+          
+          QualType ParamTypes[2] = { *Ptr, *Ptr };
           AddBuiltinCandidate(Context.getPointerDiffType(), ParamTypes,
                               Args, 2, CandidateSet);
         }
-      }
+      }   
+      
+      AddedTypes.clear();
     }
     // Fall through
 
@@ -4942,12 +4999,13 @@
 
     // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the
     // conditional operator for vector types.
-    for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(),
-         Vec1End = CandidateTypes.vector_end(); 
+    for (BuiltinCandidateTypeSet::iterator
+              Vec1 = CandidateTypes[0].vector_begin(),
+           Vec1End = CandidateTypes[0].vector_end(); 
          Vec1 != Vec1End; ++Vec1)
       for (BuiltinCandidateTypeSet::iterator 
-           Vec2 = CandidateTypes.vector_begin(),
-           Vec2End = CandidateTypes.vector_end(); 
+               Vec2 = CandidateTypes[1].vector_begin(),
+             Vec2End = CandidateTypes[1].vector_end(); 
            Vec2 != Vec2End; ++Vec2) {
         QualType LandR[2] = { *Vec1, *Vec2 };
         QualType Result;
@@ -5006,18 +5064,30 @@
     //   empty, there exist candidate operator functions of the form
     //
     //        VQ T&      operator=(VQ T&, T);
-    for (BuiltinCandidateTypeSet::iterator
-           Enum = CandidateTypes.enumeration_begin(),
-           EnumEnd = CandidateTypes.enumeration_end();
-         Enum != EnumEnd; ++Enum)
-      AddBuiltinAssignmentOperatorCandidates(*this, *Enum, Args, 2,
-                                             CandidateSet);
-    for (BuiltinCandidateTypeSet::iterator
-           MemPtr = CandidateTypes.member_pointer_begin(),
-         MemPtrEnd = CandidateTypes.member_pointer_end();
-         MemPtr != MemPtrEnd; ++MemPtr)
-      AddBuiltinAssignmentOperatorCandidates(*this, *MemPtr, Args, 2,
-                                             CandidateSet);
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+             EnumEnd = CandidateTypes[ArgIdx].enumeration_end();
+           Enum != EnumEnd; ++Enum) {
+        if (!AddedTypes.insert(Context.getCanonicalType(*Enum)))
+          continue;
+        
+        AddBuiltinAssignmentOperatorCandidates(*this, *Enum, Args, 2,
+                                               CandidateSet);
+      }
+      
+      for (BuiltinCandidateTypeSet::iterator
+                MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end();
+           MemPtr != MemPtrEnd; ++MemPtr) {
+        if (!AddedTypes.insert(Context.getCanonicalType(*MemPtr)))
+          continue;
+        
+        AddBuiltinAssignmentOperatorCandidates(*this, *MemPtr, Args, 2,
+                                               CandidateSet);
+      }
+    }
+    AddedTypes.clear();
       
     // Fall through.
 
@@ -5039,11 +5109,17 @@
     //
     //        T*VQ&      operator+=(T*VQ&, ptrdiff_t);
     //        T*VQ&      operator-=(T*VQ&, ptrdiff_t);
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
-         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+    for (BuiltinCandidateTypeSet::iterator 
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
       QualType ParamTypes[2];
       ParamTypes[1] = (Op == OO_Equal)? *Ptr : Context.getPointerDiffType();
 
+      // If this is operator=, keep track of the builtin candidates we added.
+      if (Op == OO_Equal)
+        AddedTypes.insert(Context.getCanonicalType(*Ptr));
+      
       // non-volatile version
       ParamTypes[0] = Context.getLValueReferenceType(*Ptr);
       AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
@@ -5058,6 +5134,33 @@
                             /*IsAssigmentOperator=*/Op == OO_Equal);
       }
     }
+      
+    if (Op == OO_Equal) {
+      for (BuiltinCandidateTypeSet::iterator 
+                Ptr = CandidateTypes[1].pointer_begin(),
+             PtrEnd = CandidateTypes[1].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        // Make sure we don't add the same candidate twice.
+        if (!AddedTypes.insert(Context.getCanonicalType(*Ptr)))
+          continue;
+        
+        QualType ParamTypes[2] = { Context.getLValueReferenceType(*Ptr), *Ptr };
+        
+        // non-volatile version
+        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                            /*IsAssigmentOperator=*/true);
+        
+        if (!Context.getCanonicalType(*Ptr).isVolatileQualified() &&
+            VisibleTypeConversionsQuals.hasVolatile()) {
+          // volatile version
+          ParamTypes[0]
+            = Context.getLValueReferenceType(Context.getVolatileType(*Ptr));
+          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,
+                              /*IsAssigmentOperator=*/true);
+        }
+      }
+      AddedTypes.clear();
+    }
     // Fall through.
 
   case OO_StarEqual:
@@ -5096,12 +5199,13 @@
     }
       
     // Extension: Add the binary operators =, +=, -=, *=, /= for vector types.
-    for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(),
-                                        Vec1End = CandidateTypes.vector_end(); 
+    for (BuiltinCandidateTypeSet::iterator
+              Vec1 = CandidateTypes[0].vector_begin(),
+           Vec1End = CandidateTypes[0].vector_end(); 
          Vec1 != Vec1End; ++Vec1)
       for (BuiltinCandidateTypeSet::iterator 
-                Vec2 = CandidateTypes.vector_begin(),
-             Vec2End = CandidateTypes.vector_end(); 
+                Vec2 = CandidateTypes[1].vector_begin(),
+             Vec2End = CandidateTypes[1].vector_end(); 
            Vec2 != Vec2End; ++Vec2) {
         QualType ParamTypes[2];
         ParamTypes[1] = *Vec2;
@@ -5200,20 +5304,29 @@
     //        T*         operator-(T*, ptrdiff_t);     [ABOVE]
     //        T*         operator+(ptrdiff_t, T*);     [ABOVE]
     //        T&         operator[](ptrdiff_t, T*);
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin();
-         Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+    for (BuiltinCandidateTypeSet::iterator 
+              Ptr = CandidateTypes[0].pointer_begin(),
+           PtrEnd = CandidateTypes[0].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
       QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() };
       QualType PointeeType = (*Ptr)->getPointeeType();
       QualType ResultTy = Context.getLValueReferenceType(PointeeType);
 
       // T& operator[](T*, ptrdiff_t)
       AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
-
-      // T& operator[](ptrdiff_t, T*);
-      ParamTypes[0] = ParamTypes[1];
-      ParamTypes[1] = *Ptr;
+    }
+      
+    for (BuiltinCandidateTypeSet::iterator 
+              Ptr = CandidateTypes[1].pointer_begin(),
+           PtrEnd = CandidateTypes[1].pointer_end();
+         Ptr != PtrEnd; ++Ptr) {
+      QualType ParamTypes[2] = { Context.getPointerDiffType(), *Ptr };
+      QualType PointeeType = (*Ptr)->getPointeeType();
+      QualType ResultTy = Context.getLValueReferenceType(PointeeType);
+      
+      // T& operator[](ptrdiff_t, T*)
       AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet);
-    }      
+    }
     break;
 
   case OO_ArrowStar:
@@ -5222,12 +5335,15 @@
     //    C1 is the same type as C2 or is a derived class of C2, T is an object 
     //    type or a function type, and CV1 and CV2 are cv-qualifier-seqs, 
     //    there exist candidate operator functions of the form 
-    //    CV12 T& operator->*(CV1 C1*, CV2 T C2::*); 
+    //
+    //      CV12 T& operator->*(CV1 C1*, CV2 T C2::*); 
+    //
     //    where CV12 is the union of CV1 and CV2.
     {
-      for (BuiltinCandidateTypeSet::iterator Ptr = 
-             CandidateTypes.pointer_begin();
-           Ptr != CandidateTypes.pointer_end(); ++Ptr) {
+      for (BuiltinCandidateTypeSet::iterator 
+               Ptr = CandidateTypes[0].pointer_begin(),
+             PtrEnd = CandidateTypes[0].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
         QualType C1Ty = (*Ptr);
         QualType C1;
         QualifierCollector Q1;
@@ -5242,8 +5358,8 @@
         if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict())
           continue;
         for (BuiltinCandidateTypeSet::iterator
-             MemPtr = CandidateTypes.member_pointer_begin(),
-             MemPtrEnd = CandidateTypes.member_pointer_end();
+                  MemPtr = CandidateTypes[1].member_pointer_begin(),
+               MemPtrEnd = CandidateTypes[1].member_pointer_end();
              MemPtr != MemPtrEnd; ++MemPtr) {
           const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr);
           QualType C2 = QualType(mptr->getClass(), 0);
@@ -5278,25 +5394,44 @@
     //
     //        T        operator?(bool, T, T);
     //
-    for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(),
-         E = CandidateTypes.pointer_end(); Ptr != E; ++Ptr) {
-      QualType ParamTypes[2] = { *Ptr, *Ptr };
-      AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
-    }
-    for (BuiltinCandidateTypeSet::iterator Ptr =
-           CandidateTypes.member_pointer_begin(),
-         E = CandidateTypes.member_pointer_end(); Ptr != E; ++Ptr) {
-      QualType ParamTypes[2] = { *Ptr, *Ptr };
-      AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
-    }
-    if (getLangOptions().CPlusPlus0x)
-    for (BuiltinCandidateTypeSet::iterator Enum =
-         CandidateTypes.enumeration_begin(),
-         E = CandidateTypes.enumeration_end(); Enum != E; ++Enum) {
-      if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
-        continue;
-      QualType ParamTypes[2] = { *Enum, *Enum };
-      AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet);
+    for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+      for (BuiltinCandidateTypeSet::iterator
+                Ptr = CandidateTypes[ArgIdx].pointer_begin(),
+             PtrEnd = CandidateTypes[ArgIdx].pointer_end();
+           Ptr != PtrEnd; ++Ptr) {
+        if (!AddedTypes.insert(Context.getCanonicalType(*Ptr)))
+          continue;
+        
+        QualType ParamTypes[2] = { *Ptr, *Ptr };
+        AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet);
+      }
+      
+      for (BuiltinCandidateTypeSet::iterator 
+                MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(),
+             MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); 
+           MemPtr != MemPtrEnd; ++MemPtr) {
+        if (!AddedTypes.insert(Context.getCanonicalType(*MemPtr)))
+          continue;
+        
+        QualType ParamTypes[2] = { *MemPtr, *MemPtr };
+        AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet);
+      }
+      
+      if (getLangOptions().CPlusPlus0x) {
+        for (BuiltinCandidateTypeSet::iterator 
+                  Enum = CandidateTypes[ArgIdx].enumeration_begin(),
+               EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); 
+             Enum != EnumEnd; ++Enum) {
+          if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped())
+            continue;
+          
+          if (!AddedTypes.insert(Context.getCanonicalType(*Enum)))
+            continue;
+
+          QualType ParamTypes[2] = { *Enum, *Enum };
+          AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet);
+        }
+      }
     }
     goto Conditional;
   }

Modified: cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp?rev=118178&r1=118177&r2=118178&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-builtin-operators.cpp Wed Nov  3 12:00:07 2010
@@ -200,3 +200,23 @@
     if (e1 > e2) {}
   }
 }
+
+namespace PR8477 {
+  struct Foo {
+    operator bool();
+    operator const char *();
+  };
+
+  bool doit() {
+    Foo foo;
+    long long zero = 0;
+    (void)(foo + zero);
+    (void)(foo - zero);
+    (void)(zero + foo);
+    (void)(zero[foo]);
+    (void)(foo - foo); // expected-error{{use of overloaded operator '-' is ambiguous}} \
+    // expected-note 4{{built-in candidate operator-}} \
+    // expected-note{{candidates omitted}}
+    return foo[zero] == zero;
+  }
+}





More information about the cfe-commits mailing list