From 2a7e58dc24b17b1cb900a1ee30ea328d665b1a64 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 23 Dec 2008 00:53:59 +0000 Subject: [PATCH] Add some block-pointer conversions in C++ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61359 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 31 ++++++++++++++++++++----------- test/SemaObjC/blocks.m | 4 ++++ test/SemaObjCXX/blocks.mm | 26 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 test/SemaObjCXX/blocks.mm diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 8463c5d34b..b2130e42f8 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -135,7 +135,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const // check for their presence as well as checking whether FromType is // a pointer. if (ToType->isBooleanType() && - (FromType->isPointerType() || + (FromType->isPointerType() || FromType->isBlockPointerType() || First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) return true; @@ -547,7 +547,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, else if (ToType->isBooleanType() && (FromType->isArithmeticType() || FromType->isEnumeralType() || - FromType->isPointerType())) { + FromType->isPointerType() || + FromType->isBlockPointerType())) { SCS.Second = ICK_Boolean_Conversion; FromType = Context.BoolTy; } else { @@ -857,25 +858,33 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, return true; } + // Beyond this point, both types need to be pointers or block pointers. + QualType ToPointeeType; const PointerType* ToTypePtr = ToType->getAsPointerType(); - if (!ToTypePtr) + if (ToTypePtr) + ToPointeeType = ToTypePtr->getPointeeType(); + else if (const BlockPointerType *ToBlockPtr = ToType->getAsBlockPointerType()) + ToPointeeType = ToBlockPtr->getPointeeType(); + else return false; - // Beyond this point, both types need to be pointers. + QualType FromPointeeType; const PointerType *FromTypePtr = FromType->getAsPointerType(); - if (!FromTypePtr) + if (FromTypePtr) + FromPointeeType = FromTypePtr->getPointeeType(); + else if (const BlockPointerType *FromBlockPtr + = FromType->getAsBlockPointerType()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else return false; - QualType FromPointeeType = FromTypePtr->getPointeeType(); - QualType ToPointeeType = ToTypePtr->getPointeeType(); - // Objective C++: We're able to convert from a pointer to an // interface to a pointer to a different interface. const ObjCInterfaceType* FromIface = FromPointeeType->getAsObjCInterfaceType(); const ObjCInterfaceType* ToIface = ToPointeeType->getAsObjCInterfaceType(); if (FromIface && ToIface && Context.canAssignObjCInterfaces(ToIface, FromIface)) { - ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, ToType, Context); return true; @@ -887,7 +896,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // interfaces, which is permitted. However, we're going to // complain about it. IncompatibleObjC = true; - ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, ToType, Context); return true; @@ -924,7 +933,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, return true; } - // If we have pointers to functions, check whether the only + // If we have pointers to functions or blocks, check whether the only // differences in the argument and result types are in Objective-C // pointer conversions. If so, we permit the conversion (but // complain about it). diff --git a/test/SemaObjC/blocks.m b/test/SemaObjC/blocks.m index dd8380aea9..8e72be6e37 100644 --- a/test/SemaObjC/blocks.m +++ b/test/SemaObjC/blocks.m @@ -20,3 +20,7 @@ void bar4(id(^)()); void foo4(id (^objectCreationBlock)(int)) { return bar4(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)()'}} } + +void foo5(id (^x)(int)) { + if (x) { } +} diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm new file mode 100644 index 0000000000..8aee15266e --- /dev/null +++ b/test/SemaObjCXX/blocks.mm @@ -0,0 +1,26 @@ +// RUN: clang -fsyntax-only -verify -fblocks %s +@protocol NSObject; + +void bar(id(^)(void)); +void foo(id (^objectCreationBlock)(void)) { + return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)(void)', expected 'id (^)(void)'}} +} + +void bar2(id(*)(void)); +void foo2(id (*objectCreationBlock)(void)) { + return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)(void)', expected 'id (*)(void)'}} +} + +void bar3(id(*)()); +void foo3(id (*objectCreationBlock)(int)) { + return bar3(objectCreationBlock); // expected-error{{incompatible type passing 'id (*)(int)', expected 'id (*)(void)'}} +} + +void bar4(id(^)()); +void foo4(id (^objectCreationBlock)(int)) { + return bar4(objectCreationBlock); // expected-error{{incompatible type passing 'id (^)(int)', expected 'id (^)(void)'}} +} + +void foo5(id (^x)(int)) { + if (x) { } +}