From: Fariborz Jahanian Date: Wed, 16 Dec 2009 23:13:33 +0000 (+0000) Subject: Allow pointer convesion of an objective-c pointer to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=adcfab1ffcb754672fb943832e04a79593a07a49;p=clang Allow pointer convesion of an objective-c pointer to 'void *' to mimic gcc's behavior. (fixes radar 7477351). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91570 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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(); 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