const FunctionType *rbase = rhs->getAsFunctionType();
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(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
/// function type for the block, including the first block literal argument.
static QualType getBlockFunctionType(ASTContext &Ctx,
const BlockPointerType *BPT) {
- const FunctionProtoType *FTy = cast<FunctionProtoType>(BPT->getPointeeType());
+ const FunctionProtoType *FTy = dyn_cast<FunctionProtoType>(BPT->getPointeeType());
+ const clang::QualType ResType = BPT->getPointeeType()->getAsFunctionType()->getResultType();
llvm::SmallVector<QualType, 8> 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) {
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 (^)()'}}
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}}
}
// 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;
+}
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) { }
}