Fix block comparisons. Radar 6732116.

llvm-svn: 68171
This commit is contained in:
Mike Stump 2009-04-01 01:17:39 +00:00
parent 237f349073
commit cafa0a9746
5 changed files with 55 additions and 39 deletions

View File

@ -2701,9 +2701,9 @@ bool ASTContext::typesAreBlockCompatible(QualType lhs, QualType rhs) {
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

View File

@ -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<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) {

View File

@ -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 (^)()'}}

View File

@ -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;
}

View File

@ -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) { }
}