From d1a2d5719aa594f99585c8e127c63181965c707a Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 15 Dec 2009 17:30:20 +0000 Subject: [PATCH] Implement conditional block invocation rewrite and some clean up and a block rewriter test. llvm-svn: 91435 --- clang/lib/Frontend/RewriteObjC.cpp | 40 +++++++---- clang/test/Rewriter/rewrite-block-literal.c | 80 +++++++++++++++++++++ 2 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 clang/test/Rewriter/rewrite-block-literal.c diff --git a/clang/lib/Frontend/RewriteObjC.cpp b/clang/lib/Frontend/RewriteObjC.cpp index df85c13cea78..6f8d40f0d133 100644 --- a/clang/lib/Frontend/RewriteObjC.cpp +++ b/clang/lib/Frontend/RewriteObjC.cpp @@ -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(Exp->getCallee())) { - closureName = DRE->getDecl()->getNameAsCString(); + if (const DeclRefExpr *DRE = dyn_cast(BlockExp)) { CPT = DRE->getType()->getAs(); - } else if (BlockDeclRefExpr *CDRE = dyn_cast(Exp->getCallee())) { - closureName = CDRE->getDecl()->getNameAsCString(); + } else if (const BlockDeclRefExpr *CDRE = + dyn_cast(BlockExp)) { CPT = CDRE->getType()->getAs(); - } else if (MemberExpr *MExpr = dyn_cast(Exp->getCallee())) { - closureName = MExpr->getMemberDecl()->getNameAsCString(); + } else if (const MemberExpr *MExpr = dyn_cast(BlockExp)) { CPT = MExpr->getType()->getAs(); + } + else if (const ParenExpr *PRE = dyn_cast(BlockExp)) { + return SynthesizeBlockCall(Exp, PRE->getSubExpr()); + } + else if (const ImplicitCastExpr *IEXPR = dyn_cast(BlockExp)) + CPT = IEXPR->getType()->getAs(); + else if (const ConditionalOperator *CEXPR = + dyn_cast(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(LHSStmt), + SourceLocation(), cast(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(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(S)) { if (CE->getCallee()->getType()->isBlockPointerType()) { - Stmt *BlockCall = SynthesizeBlockCall(CE); + Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); ReplaceStmt(S, BlockCall); return BlockCall; } diff --git a/clang/test/Rewriter/rewrite-block-literal.c b/clang/test/Rewriter/rewrite-block-literal.c new file mode 100644 index 000000000000..c491f2dee4f3 --- /dev/null +++ b/clang/test/Rewriter/rewrite-block-literal.c @@ -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) { };