When comparing Objective-C pointers during overload resolution to

determine which is a better conversion to "void*", be sure to perform
the comparison using the safe-for-id
ASTContext::canAssignObjCInterfaces() rather than the asserts-with-id
ASTContext::canAssignObjCInterfaces().

Fixes <rdar://problem/9327203>.

llvm-svn: 130259
This commit is contained in:
Douglas Gregor 2011-04-27 00:01:52 +00:00
parent c5f121e3c0
commit 30ee16f5dd
2 changed files with 29 additions and 12 deletions

View File

@ -2631,7 +2631,8 @@ CompareStandardConversionSequences(Sema &S,
if (ImplicitConversionSequence::CompareKind DerivedCK
= CompareDerivedToBaseConversions(S, SCS1, SCS2))
return DerivedCK;
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid) {
} else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid &&
!S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) {
// Both conversion sequences are conversions to void
// pointers. Compare the source types to determine if there's an
// inheritance relationship in their sources.
@ -2645,10 +2646,8 @@ CompareStandardConversionSequences(Sema &S,
if (SCS2.First == ICK_Array_To_Pointer)
FromType2 = S.Context.getArrayDecayedType(FromType2);
QualType FromPointee1
= FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType FromPointee2
= FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType();
QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType();
QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType();
if (S.IsDerivedFrom(FromPointee2, FromPointee1))
return ImplicitConversionSequence::Better;
@ -2657,13 +2656,19 @@ CompareStandardConversionSequences(Sema &S,
// Objective-C++: If one interface is more specific than the
// other, it is the better one.
const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>();
const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>();
if (FromIface1 && FromIface1) {
if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1))
return ImplicitConversionSequence::Better;
else if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2))
return ImplicitConversionSequence::Worse;
const ObjCObjectPointerType* FromObjCPtr1
= FromType1->getAs<ObjCObjectPointerType>();
const ObjCObjectPointerType* FromObjCPtr2
= FromType2->getAs<ObjCObjectPointerType>();
if (FromObjCPtr1 && FromObjCPtr2) {
bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1,
FromObjCPtr2);
bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2,
FromObjCPtr1);
if (AssignLeft != AssignRight) {
return AssignLeft? ImplicitConversionSequence::Better
: ImplicitConversionSequence::Worse;
}
}
}

View File

@ -159,3 +159,15 @@ namespace PR9735 {
int &ir2 = f3(bc);
}
}
@interface D : B
@end
namespace rdar9327203 {
int &f(void* const&, int);
float &f(void* const&, long);
void g(id x) {
int &fr = (f)(x, 0);
}
}