diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cede0e556391..bdc7e4484c2b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2701,9 +2701,9 @@ bool ASTContext::typesAreBlockCompatible(QualType lhs, QualType rhs) { const FunctionType *rbase = rhs->getAsFunctionType(); const FunctionProtoType *lproto = dyn_cast(lbase); const FunctionProtoType *rproto = dyn_cast(rbase); - if (lproto && rproto) - return !mergeTypes(lhs, rhs).isNull(); - return false; + if (lproto && rproto == 0) + return false; + return !mergeTypes(lhs, rhs).isNull(); } /// areCompatVectorTypes - Return true if the two specified vector types are diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 16e926ba643c..c05d3235dd89 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -412,18 +412,19 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() { /// function type for the block, including the first block literal argument. static QualType getBlockFunctionType(ASTContext &Ctx, const BlockPointerType *BPT) { - const FunctionProtoType *FTy = cast(BPT->getPointeeType()); + const FunctionProtoType *FTy = dyn_cast(BPT->getPointeeType()); + const clang::QualType ResType = BPT->getPointeeType()->getAsFunctionType()->getResultType(); llvm::SmallVector Types; Types.push_back(Ctx.getPointerType(Ctx.VoidTy)); - for (FunctionProtoType::arg_type_iterator i = FTy->arg_type_begin(), - e = FTy->arg_type_end(); i != e; ++i) - Types.push_back(*i); + if (FTy) + for (FunctionProtoType::arg_type_iterator i = FTy->arg_type_begin(), + e = FTy->arg_type_end(); i != e; ++i) + Types.push_back(*i); - return Ctx.getFunctionType(FTy->getResultType(), - &Types[0], Types.size(), - FTy->isVariadic(), 0); + return Ctx.getFunctionType(ResType, &Types[0], Types.size(), + FTy && FTy->isVariadic(), 0); } RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { diff --git a/clang/test/Sema/block-call.c b/clang/test/Sema/block-call.c index 3326131816e7..34de8b611d8a 100644 --- a/clang/test/Sema/block-call.c +++ b/clang/test/Sema/block-call.c @@ -10,7 +10,7 @@ int main() { int (^PFR) (int) = IFP; // expected-warning {{incompatible block pointer types initializing 'int (^)()', expected 'int (^)(int)'}} PFR = II; // OK - int (^IFP) () = PFR; // expected-warning {{incompatible block pointer types initializing 'int (^)(int)', expected 'int (^)()'}} + int (^IFP) () = PFR; const int (^CIC) () = IFP; // expected-warning {{incompatible block pointer types initializing 'int (^)()', expected 'int const (^)()'}} diff --git a/clang/test/Sema/block-misc.c b/clang/test/Sema/block-misc.c index dde07f073949..ea3477d2639d 100644 --- a/clang/test/Sema/block-misc.c +++ b/clang/test/Sema/block-misc.c @@ -4,48 +4,48 @@ void donotwarn(); int (^IFP) (); int (^II) (int); int test1() { - int (^PFR) (int) = 0; // OK - PFR = II; // OK + int (^PFR) (int) = 0; // OK + PFR = II; // OK - if (PFR == II) // OK - donotwarn(); + if (PFR == II) // OK + donotwarn(); - if (PFR == IFP) // expected-error {{comparison of distinct block types}} - donotwarn(); + if (PFR == IFP) // expected-error {{comparison of distinct block types}} + donotwarn(); - if (PFR == (int (^) (int))IFP) // OK - donotwarn(); + if (PFR == (int (^) (int))IFP) // OK + donotwarn(); - if (PFR == 0) // OK - donotwarn(); + if (PFR == 0) // OK + donotwarn(); - if (PFR) // OK - donotwarn(); + if (PFR) // OK + donotwarn(); - if (!PFR) // OK - donotwarn(); + if (!PFR) // OK + donotwarn(); - return PFR != IFP; // expected-error {{comparison of distinct block types}} + return PFR != IFP; // expected-error {{comparison of distinct block types}} } int test2(double (^S)()) { - double (^I)(int) = (void*) S; - (void*)I = (void *)S; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} + double (^I)(int) = (void*) S; + (void*)I = (void *)S; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} - void *pv = I; + void *pv = I; - pv = S; + pv = S; - I(1); - - return (void*)I == (void *)S; + I(1); + + return (void*)I == (void *)S; } int^ x; // expected-error {{block pointer to non-function type is invalid}} int^^ x1; // expected-error {{block pointer to non-function type is invalid}} expected-error {{block pointer to non-function type is invalid}} int test3() { - char *^ y; // expected-error {{block pointer to non-function type is invalid}} + char *^ y; // expected-error {{block pointer to non-function type is invalid}} } @@ -72,8 +72,13 @@ void test5() { // rdar://6405429 - __func__ in a block refers to the containing function name. const char*test6() { - return ^{ - return __func__; - } (); + return ^{ + return __func__; + } (); } +// radr://6732116 - block comparisons +void (^g)(); +int foo(void (^p)()) { + return g == p; +} diff --git a/clang/test/SemaObjC/blocks.m b/clang/test/SemaObjC/blocks.m index 6d525a990ca1..fe14287c7edb 100644 --- a/clang/test/SemaObjC/blocks.m +++ b/clang/test/SemaObjC/blocks.m @@ -18,9 +18,19 @@ void foo3(id (*objectCreationBlock)(int)) { void bar4(id(^)()); void foo4(id (^objectCreationBlock)(int)) { - return bar4(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)()'}} + return bar4(objectCreationBlock); } -void foo5(id (^x)(int)) { +void bar5(id(^)(void)); +void foo5(id (^objectCreationBlock)(int)) { + return bar5(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)(void)'}} +} + +void bar6(id(^)(int)); +void foo6(id (^objectCreationBlock)()) { + return bar6(objectCreationBlock); // expected-warning{{incompatible block pointer types passing 'id (^)()', expected 'id (^)(int)'}} +} + +void foo67(id (^x)(int)) { if (x) { } }