Implement conditional block invocation rewrite

and some clean up and a block rewriter test.

llvm-svn: 91435
This commit is contained in:
Fariborz Jahanian 2009-12-15 17:30:20 +00:00
parent c28e629c2d
commit d1a2d5719a
2 changed files with 108 additions and 12 deletions

View File

@ -337,7 +337,7 @@ namespace {
std::string ImplTag,
int i, const char *funcName,
unsigned hasCopy);
Stmt *SynthesizeBlockCall(CallExpr *Exp);
Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
void SynthesizeBlockLiterals(SourceLocation FunLocStart,
const char *FunName);
void RewriteRecordBody(RecordDecl *RD);
@ -4030,20 +4030,36 @@ void RewriteObjC::GetBlockCallExprs(Stmt *S) {
return;
}
Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
// Navigate to relevant type information.
const char *closureName = 0;
const BlockPointerType *CPT = 0;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp->getCallee())) {
closureName = DRE->getDecl()->getNameAsCString();
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
CPT = DRE->getType()->getAs<BlockPointerType>();
} else if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(Exp->getCallee())) {
closureName = CDRE->getDecl()->getNameAsCString();
} else if (const BlockDeclRefExpr *CDRE =
dyn_cast<BlockDeclRefExpr>(BlockExp)) {
CPT = CDRE->getType()->getAs<BlockPointerType>();
} else if (MemberExpr *MExpr = dyn_cast<MemberExpr>(Exp->getCallee())) {
closureName = MExpr->getMemberDecl()->getNameAsCString();
} else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
CPT = MExpr->getType()->getAs<BlockPointerType>();
}
else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
return SynthesizeBlockCall(Exp, PRE->getSubExpr());
}
else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
CPT = IEXPR->getType()->getAs<BlockPointerType>();
else if (const ConditionalOperator *CEXPR =
dyn_cast<ConditionalOperator>(BlockExp)) {
Expr *LHSExp = CEXPR->getLHS();
Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
Expr *RHSExp = CEXPR->getRHS();
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
Expr *CONDExp = CEXPR->getCond();
ConditionalOperator *CondExpr =
new (Context) ConditionalOperator(CONDExp,
SourceLocation(), cast<Expr>(LHSStmt),
SourceLocation(), cast<Expr>(RHSStmt),
Exp->getType());
return CondExpr;
} else {
assert(1 && "RewriteBlockClass: Bad type");
}
@ -4083,7 +4099,7 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
CastExpr *BlkCast = new (Context) CStyleCastExpr(PtrBlock,
CastExpr::CK_Unknown,
Exp->getCallee(),
const_cast<Expr*>(BlockExp),
PtrBlock, SourceLocation(),
SourceLocation());
// Don't forget the parens to enforce the proper binding.
@ -4119,7 +4135,7 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp) {
}
void RewriteObjC::RewriteBlockCall(CallExpr *Exp) {
Stmt *BlockCall = SynthesizeBlockCall(Exp);
Stmt *BlockCall = SynthesizeBlockCall(Exp, Exp->getCallee());
ReplaceStmt(Exp, BlockCall);
}
@ -4668,7 +4684,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
}
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
if (CE->getCallee()->getType()->isBlockPointerType()) {
Stmt *BlockCall = SynthesizeBlockCall(CE);
Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
ReplaceStmt(S, BlockCall);
return BlockCall;
}

View File

@ -0,0 +1,80 @@
// RUN: clang -cc1 -rewrite-objc %s -fblocks -o -
void I( void (^)(void));
void (^noop)(void);
void nothing();
int printf(const char*, ...);
typedef void (^T) (void);
void takeblock(T);
int takeintint(int (^C)(int)) { return C(4); }
T somefunction() {
if (^{ })
nothing();
noop = ^{};
noop = ^{printf("\nClosure\n"); };
I(^{ });
return ^{printf("\nClosure\n"); };
}
void test2() {
int x = 4;
takeblock(^{ printf("%d\n", x); });
while (1) {
takeblock(^{
while(1) break; // ok
});
break;
}
}
void (^test3())(void) {
return ^{};
}
void test4() {
void (^noop)(void) = ^{};
void (*noop2)() = 0;
}
void myfunc(int (^block)(int)) {}
void myfunc3(const int *x);
void test5() {
int a;
myfunc(^(int abcd) {
myfunc3(&a);
return 1;
});
}
void *X;
void test_arguments() {
int y;
int (^c)(char);
(1 ? c : 0)('x');
(1 ? 0 : c)('x');
(1 ? c : c)('x');
}
static int global_x = 10;
void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); };
typedef void (^void_block_t)(void);
static const void_block_t myBlock = ^{ };
static const void_block_t myBlock2 = ^ void(void) { };