diff options
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 30 | ||||
-rw-r--r-- | test/SemaObjCXX/objc-pointer-conv.mm | 26 |
2 files changed, 54 insertions, 2 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index a37f86dd34..4565e94ebe 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -915,6 +915,25 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, Quals)); } +/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from +/// the FromType, which is an objective-c pointer, to ToType, which may or may +/// not have the right set of qualifiers. +static QualType +BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType, + QualType ToType, + ASTContext &Context) { + QualType CanonFromType = Context.getCanonicalType(FromType); + QualType CanonToType = Context.getCanonicalType(ToType); + Qualifiers Quals = CanonFromType.getQualifiers(); + + // Exact qualifier match -> return the pointer type we're converting to. + if (CanonToType.getLocalQualifiers() == Quals) + return ToType; + + // Just build a canonical type that has the right qualifiers. + return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals); +} + static bool isNullPointerConstantForConversion(Expr *Expr, bool InOverloadResolution, ASTContext &Context) { @@ -992,13 +1011,20 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, return true; } - // Beyond this point, both types need to be pointers. + // Beyond this point, both types need to be pointers + // , including objective-c pointers. + QualType ToPointeeType = ToTypePtr->getPointeeType(); + if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType, + ToType, Context); + return true; + + } const PointerType *FromTypePtr = FromType->getAs<PointerType>(); if (!FromTypePtr) return false; QualType FromPointeeType = FromTypePtr->getPointeeType(); - QualType ToPointeeType = ToTypePtr->getPointeeType(); // An rvalue of type "pointer to cv T," where T is an object type, // can be converted to an rvalue of type "pointer to cv void" (C++ diff --git a/test/SemaObjCXX/objc-pointer-conv.mm b/test/SemaObjCXX/objc-pointer-conv.mm new file mode 100644 index 0000000000..c03e3aaad3 --- /dev/null +++ b/test/SemaObjCXX/objc-pointer-conv.mm @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +typedef const void * VoidStar; + +typedef struct __CFDictionary * CFMDRef; + +void RandomFunc(CFMDRef theDict, const void *key, const void *value); + +@interface Foo +- (void)_apply:(void (*)(const void *, const void *, void *))func context:(void *)context; +- (void)a:(id *)objects b:(id *)keys; +@end + +@implementation Foo +- (void)_apply:(void (*)(const void *, const void *, void *))func context:(void *)context { + id item; + id obj; + func(item, obj, context); +} + +- (void)a:(id *)objects b:(id *)keys { + VoidStar dict; + id key; + RandomFunc((CFMDRef)dict, key, objects[3]); +} +@end |