Don't allow defining a block with a non-prototype type. Remove a

hack which introduces some strange inconsistencies in compatibility 
for block pointers.

Note that unlike an earlier revision proposed on cfe-commits, this patch 
still allows declaring block pointers without a prototype.

llvm-svn: 73041
This commit is contained in:
Eli Friedman 2009-06-08 04:24:21 +00:00
parent f6d9fd20c2
commit 9e81b02ec5
7 changed files with 10 additions and 20 deletions

View File

@ -2853,12 +2853,6 @@ QualType::GCAttrTypes ASTContext::getObjCGCAttrKind(const QualType &Ty) const {
/// FIXME: When the dust settles on this integration, fold this into mergeTypes. /// FIXME: When the dust settles on this integration, fold this into mergeTypes.
/// ///
bool ASTContext::typesAreBlockCompatible(QualType lhs, QualType rhs) { bool ASTContext::typesAreBlockCompatible(QualType lhs, QualType rhs) {
const FunctionType *lbase = lhs->getAsFunctionType();
const FunctionType *rbase = rhs->getAsFunctionType();
const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(rbase);
if (lproto && rproto == 0)
return false;
return !mergeTypes(lhs, rhs).isNull(); return !mergeTypes(lhs, rhs).isNull();
} }

View File

@ -1011,9 +1011,7 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
CI != E; ++CI) CI != E; ++CI)
if (*CI) { if (*CI) {
if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) {
Stmt *newStmt = RewriteFunctionBody(CBE->getBody()); RewriteFunctionBody(CBE->getBody());
if (newStmt)
*CI = newStmt;
// We've just rewritten the block body in place. // We've just rewritten the block body in place.
// Now we snarf the rewritten text and stash it away for later use. // Now we snarf the rewritten text and stash it away for later use.
@ -1023,9 +1021,7 @@ Stmt *RewriteBlocks::RewriteFunctionBody(Stmt *S) {
// Do the rewrite, using S.size() which contains the rewritten size. // Do the rewrite, using S.size() which contains the rewritten size.
ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size()); ReplaceText(CBE->getLocStart(), S.size(), Init.c_str(), Init.size());
} else { } else {
Stmt *newStmt = RewriteFunctionBody(*CI); RewriteFunctionBody(*CI);
if (newStmt)
*CI = newStmt;
} }
} }
// Handle specific things. // Handle specific things.

View File

@ -5220,7 +5220,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
QualType BlockTy; QualType BlockTy;
if (!BSI->hasPrototype) if (!BSI->hasPrototype)
BlockTy = Context.getFunctionNoProtoType(RetTy); BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0);
else else
BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(), BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(),
BSI->isVariadic, 0); BSI->isVariadic, 0);

View File

@ -18,7 +18,7 @@ void test() {
^{return 1;}(); ^{return 1;}();
^{return 2;}(arg); // expected-error {{too many arguments to block call}} ^{return 2;}(arg); // expected-error {{too many arguments to block call}}
^(void){return 3;}(1); // expected-error {{too many arguments to block call}} ^(void){return 3;}(1); // expected-error {{too many arguments to block call}}
^(){return 4;}(arg); // C style (...), ok. ^(){return 4;}(arg); // expected-error {{too many arguments to block call}}
^(int x, ...){return 5;}(arg, arg); // Explicit varargs, ok. ^(int x, ...){return 5;}(arg, arg); // Explicit varargs, ok.
} }

View File

@ -7,10 +7,10 @@ int main() {
int (*FPL) (int) = FP; // C doesn't consider this an error. int (*FPL) (int) = FP; // C doesn't consider this an error.
// For Blocks, the ASTContext::typesAreBlockCompatible() makes sure this is an error. // For Blocks, the ASTContext::typesAreBlockCompatible() makes sure this is an error.
int (^PFR) (int) = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int (^)(int)'}} int (^PFR) (int) = IFP; // OK
PFR = II; // OK PFR = II; // OK
int (^IFP) () = PFR; int (^IFP) () = PFR; // OK
const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int const (^)()'}} const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int const (^)()'}}

View File

@ -10,7 +10,7 @@ int test1() {
if (PFR == II) // OK if (PFR == II) // OK
donotwarn(); donotwarn();
if (PFR == IFP) // expected-error {{comparison of distinct block types}} if (PFR == IFP) // OK
donotwarn(); donotwarn();
if (PFR == (int (^) (int))IFP) // OK if (PFR == (int (^) (int))IFP) // OK
@ -25,7 +25,7 @@ int test1() {
if (!PFR) // OK if (!PFR) // OK
donotwarn(); donotwarn();
return PFR != IFP; // expected-error {{comparison of distinct block types}} return PFR != IFP; // OK
} }
int test2(double (^S)()) { int test2(double (^S)()) {
@ -165,7 +165,7 @@ void test17() {
f(1 ? bp : vp); f(1 ? bp : vp);
f(1 ? vp : bp); f(1 ? vp : bp);
f(1 ? bp : bp1); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (^)()')}} f(1 ? bp : bp1);
(void)(bp > rp); // expected-error {{invalid operands}} (void)(bp > rp); // expected-error {{invalid operands}}
(void)(bp > 0); // expected-error {{invalid operands}} (void)(bp > 0); // expected-error {{invalid operands}}
(void)(bp > bp); // expected-error {{invalid operands}} (void)(bp > bp); // expected-error {{invalid operands}}

View File

@ -28,7 +28,7 @@ void foo5(id (^objectCreationBlock)(int)) {
void bar6(id(^)(int)); void bar6(id(^)(int));
void foo6(id (^objectCreationBlock)()) { void foo6(id (^objectCreationBlock)()) {
return bar6(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)()', expected 'id (^)(int)'}} return bar6(objectCreationBlock);
} }
void foo7(id (^x)(int)) { void foo7(id (^x)(int)) {