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);
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");
}
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.
}
void RewriteObjC::RewriteBlockCall(CallExpr *Exp) {
- Stmt *BlockCall = SynthesizeBlockCall(Exp);
+ Stmt *BlockCall = SynthesizeBlockCall(Exp, Exp->getCallee());
ReplaceStmt(Exp, BlockCall);
}
}
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;
}
--- /dev/null
+// 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) { };