From: Douglas Gregor Date: Wed, 21 Oct 2009 22:01:30 +0000 (+0000) Subject: Don't generate pointer types for void or base classes when finding X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=652371ad0427b2310ff01ea22fdc37f02d19abe8;p=clang Don't generate pointer types for void or base classes when finding conversion types for builtin overloaded operator candidates; I misread this section in the standard the first time around. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84788 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index f5a7d18980..9611bb20b9 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -3053,32 +3053,6 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, // of types. if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals)) return; - - // Add 'cv void*' to our set of types. - if (!Ty->isVoidType()) { - QualType QualVoid - = Context.getCVRQualifiedType(Context.VoidTy, - PointeeTy.getCVRQualifiers()); - AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid), - VisibleQuals); - } - - // If this is a pointer to a class type, add pointers to its bases - // (with the same level of cv-qualification as the original - // derived class, of course). - if (const RecordType *PointeeRec = PointeeTy->getAs()) { - CXXRecordDecl *ClassDecl = cast(PointeeRec->getDecl()); - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); - Base != ClassDecl->bases_end(); ++Base) { - QualType BaseTy = Context.getCanonicalType(Base->getType()); - BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(), - PointeeTy.getCVRQualifiers()); - // Add the pointer type, recursively, so that we get all of - // the indirect base classes, too. - AddTypesConvertedFrom(Context.getPointerType(BaseTy), false, false, - VisibleQuals); - } - } } else if (Ty->isMemberPointerType()) { // Member pointers are far easier, since the pointee can't be converted. if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty)) @@ -3224,7 +3198,17 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy, Context.FloatTy, Context.DoubleTy, Context.LongDoubleTy }; - + assert(ArithmeticTypes[FirstPromotedIntegralType] == Context.IntTy && + "Invalid first promoted integral type"); + assert(ArithmeticTypes[LastPromotedIntegralType - 1] + == Context.UnsignedLongLongTy && + "Invalid last promoted integral type"); + assert(ArithmeticTypes[FirstPromotedArithmeticType] == Context.IntTy && + "Invalid first promoted arithmetic type"); + assert(ArithmeticTypes[LastPromotedArithmeticType - 1] + == Context.LongDoubleTy && + "Invalid last promoted arithmetic type"); + // Find all of the types that the arguments can convert to, but only // if the operator we're looking at has built-in operator candidates // that make use of these types. diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp index 0284b2929b..13777daf2d 100644 --- a/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -150,3 +150,28 @@ void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr, void test_assign_restrictions(ShortRef& sr) { sr = (short)0; // expected-error{{no viable overloaded '='}} } + +struct Base { }; +struct Derived1 : Base { }; +struct Derived2 : Base { }; + +template +struct ConvertibleToPtrOf { + operator T*(); +}; + +bool test_with_base_ptrs(ConvertibleToPtrOf d1, + ConvertibleToPtrOf d2) { + return d1 == d2; // expected-error{{invalid operands}} +} + +// DR425 +struct A { + template< typename T > operator T() const; +}; + +void test_dr425(A a) { + // FIXME: lots of candidates here! + (void)(1.0f * a); // expected-error{{ambiguous}} \ + // expected-note 81{{candidate}} +}