diff options
-rw-r--r-- | lib/AST/ASTContext.cpp | 21 | ||||
-rw-r--r-- | test/Sema/block-call.c | 2 | ||||
-rw-r--r-- | test/SemaObjC/blocks.m | 22 |
3 files changed, 43 insertions, 2 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 35647cf02a..ba61332a44 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1920,7 +1920,13 @@ bool ASTContext::isObjCObjectPointerType(QualType Ty) const { /// FIXME: When the dust settles on this integration, fold this into mergeTypes. /// bool ASTContext::typesAreBlockCompatible(QualType lhs, QualType rhs) { - return getCanonicalType(lhs) == getCanonicalType(rhs); + const FunctionType *lbase = lhs->getAsFunctionType(); + const FunctionType *rbase = rhs->getAsFunctionType(); + const FunctionTypeProto *lproto = dyn_cast<FunctionTypeProto>(lbase); + const FunctionTypeProto *rproto = dyn_cast<FunctionTypeProto>(rbase); + if (lproto && rproto) + return !mergeTypes(lhs, rhs).isNull(); + return false; } /// areCompatVectorTypes - Return true if the two specified vector types are @@ -2179,6 +2185,19 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { return RHS; return getPointerType(ResultType); } + case Type::BlockPointer: + { + // Merge two block pointer types, while trying to preserve typedef info + QualType LHSPointee = LHS->getAsBlockPointerType()->getPointeeType(); + QualType RHSPointee = RHS->getAsBlockPointerType()->getPointeeType(); + QualType ResultType = mergeTypes(LHSPointee, RHSPointee); + if (ResultType.isNull()) return QualType(); + if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType)) + return LHS; + if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType)) + return RHS; + return getBlockPointerType(ResultType); + } case Type::ConstantArray: { const ConstantArrayType* LCAT = getAsConstantArrayType(LHS); diff --git a/test/Sema/block-call.c b/test/Sema/block-call.c index 66bf725922..c52f0ed96b 100644 --- a/test/Sema/block-call.c +++ b/test/Sema/block-call.c @@ -24,7 +24,7 @@ int main() { int * (^IPCC2) () = IPCC; // expected-warning {{incompatible block pointer types initializing 'int *const (^)()', expected 'int *(^)()'}} - int (^IPCC3) (const int) = PFR; // expected-warning {{incompatible block pointer types initializing 'int (^)(int)', expected 'int (^)(int const)'}} + int (^IPCC3) (const int) = PFR; int (^IPCC4) (int, char (^CArg) (double)); diff --git a/test/SemaObjC/blocks.m b/test/SemaObjC/blocks.m new file mode 100644 index 0000000000..dd8380aea9 --- /dev/null +++ b/test/SemaObjC/blocks.m @@ -0,0 +1,22 @@ +// RUN: clang -fsyntax-only -verify -fblocks %s +@protocol NSObject; + +void bar(id(^)(void)); +void foo(id <NSObject>(^objectCreationBlock)(void)) { + return bar(objectCreationBlock); +} + +void bar2(id(*)(void)); +void foo2(id <NSObject>(*objectCreationBlock)(void)) { + return bar2(objectCreationBlock); +} + +void bar3(id(*)()); +void foo3(id (*objectCreationBlock)(int)) { + return bar3(objectCreationBlock); +} + +void bar4(id(^)()); +void foo4(id (^objectCreationBlock)(int)) { + return bar4(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)()'}} +} |