From: Douglas Gregor Date: Thu, 8 Jul 2010 20:27:32 +0000 (+0000) Subject: Allow C-style casts and reinterpret_casts between block pointers and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bf9fb88e29e565061c1e91d790af6b43c25915a7;p=clang Allow C-style casts and reinterpret_casts between block pointers and either integer values or other pointers. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107905 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index d87ad6ef1c..b7e855fb1c 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -233,6 +233,15 @@ bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { T2 = T2MPType->getPointeeType(); return true; } + + const BlockPointerType *T1BPType = T1->getAs(), + *T2BPType = T2->getAs(); + if (T1BPType && T2BPType) { + T1 = T1BPType->getPointeeType(); + T2 = T2BPType->getPointeeType(); + return true; + } + return false; } @@ -246,9 +255,11 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since // the rules are non-trivial. So first we construct Tcv *...cv* as described // in C++ 5.2.11p8. - assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType()) && + assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) && "Source type is not pointer or pointer to member."); - assert((DestType->isAnyPointerType() || DestType->isMemberPointerType()) && + assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || + DestType->isBlockPointerType()) && "Destination type is not pointer or pointer to member."); QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), @@ -265,7 +276,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); cv2.push_back(DestQuals); } - assert(cv1.size() > 0 && "Must have at least one pointer level."); + if (cv1.empty()) + return false; // Construct void pointers with those qualifiers (in reverse order of // unwrapping, of course). @@ -1128,8 +1140,10 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Failed; } - bool destIsPtr = DestType->isAnyPointerType(); - bool srcIsPtr = SrcType->isAnyPointerType(); + bool destIsPtr = DestType->isAnyPointerType() || + DestType->isBlockPointerType(); + bool srcIsPtr = SrcType->isAnyPointerType() || + SrcType->isBlockPointerType(); if (!destIsPtr && !srcIsPtr) { // Except for std::nullptr_t->integer and lvalue->reference, which are // handled above, at least one of the two arguments must be a pointer. @@ -1180,11 +1194,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_cxx_cast_const_away; return TC_Failed; } + + // Cannot convert between block pointers and Objective-C object pointers. + if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) || + (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) + return TC_NotApplicable; + + // Any pointer can be cast to an Objective-C pointer type with a C-style + // cast. if (CStyle && DestType->isObjCObjectPointerType()) { Kind = CastExpr::CK_AnyPointerToObjCPointerCast; return TC_Success; } - + // Not casting away constness, so the only remaining check is for compatible // pointer categories. Kind = CastExpr::CK_BitCast; @@ -1213,7 +1235,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange; return TC_Success; } - + // C++ 5.2.10p7: A pointer to an object can be explicitly converted to // a pointer to an object of different type. // Void pointers are not specified, but supported by every compiler out there. diff --git a/test/SemaCXX/blocks-1.cpp b/test/SemaCXX/blocks-1.cpp index d93997ad68..29de1e666a 100644 --- a/test/SemaCXX/blocks-1.cpp +++ b/test/SemaCXX/blocks-1.cpp @@ -33,3 +33,13 @@ int main (int argc, const char * argv[]) { return 0; } + +namespace rdar8134521 { + void foo() { + int (^P)(int) = reinterpret_cast(1); + P = (int(^)(int))(1); + + P = reinterpret_cast((void*)1); + P = (int(^)(int))((void*)1); + } +}