From: Fariborz Jahanian Date: Tue, 29 Jan 2008 22:59:37 +0000 (+0000) Subject: Rewriting of @synchronized. This has one FIXME in it. But this should allow @sychroni... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a0f55792409289d1d343023fa8292cff6355e538;p=clang Rewriting of @synchronized. This has one FIXME in it. But this should allow @sychronized to be rewritten. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46533 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Stmt.cpp b/AST/Stmt.cpp index 0f4936b1bb..4d1be5539d 100644 --- a/AST/Stmt.cpp +++ b/AST/Stmt.cpp @@ -252,10 +252,10 @@ Stmt::child_iterator ObjCAtThrowStmt::child_end() { // ObjCAtSynchronizedStmt Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() { - return &SynchBody; + return &SubStmts[0]; } Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() { - return &SynchBody+1; + return &SubStmts[0]+END_EXPR; } diff --git a/AST/StmtSerialization.cpp b/AST/StmtSerialization.cpp index 8e743e6cb7..227f365e1c 100644 --- a/AST/StmtSerialization.cpp +++ b/AST/StmtSerialization.cpp @@ -888,15 +888,13 @@ ObjCAtFinallyStmt* ObjCAtFinallyStmt::CreateImpl(Deserializer& D) { void ObjCAtSynchronizedStmt::EmitImpl(Serializer& S) const { S.Emit(AtSynchronizedLoc); - S.BatchEmitOwnedPtrs(SynchExpr, SynchBody); -} + S.BatchEmitOwnedPtrs((unsigned) END_EXPR,&SubStmts[0]); + } ObjCAtSynchronizedStmt* ObjCAtSynchronizedStmt::CreateImpl(Deserializer& D) { SourceLocation L = SourceLocation::ReadVal(D); - Expr *syncExpr; - Stmt *synchBody; - D.BatchReadOwnedPtrs(syncExpr, synchBody); - ObjCAtSynchronizedStmt* stmt = new ObjCAtSynchronizedStmt(L,syncExpr,synchBody); + ObjCAtSynchronizedStmt* stmt = new ObjCAtSynchronizedStmt(L,0,0); + D.BatchReadOwnedPtrs((unsigned) END_EXPR, &stmt->SubStmts[0]); return stmt; } diff --git a/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index 0bcef95476..aac572177a 100644 --- a/Driver/RewriteTest.cpp +++ b/Driver/RewriteTest.cpp @@ -199,6 +199,7 @@ namespace { Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); + Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S); Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S); Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); @@ -807,6 +808,9 @@ Stmt *RewriteTest::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCAtTryStmt *StmtTry = dyn_cast(S)) return RewriteObjCTryStmt(StmtTry); + if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast(S)) + return RewriteObjCSynchronizedStmt(StmtTry); + if (ObjCAtThrowStmt *StmtThrow = dyn_cast(S)) return RewriteObjCThrowStmt(StmtThrow); @@ -903,7 +907,7 @@ Stmt *RewriteTest::RewriteContinueStmt(ContinueStmt *S) { return 0; } -/// RewriteObjCTryStmt - Rewriter for ObjC2's foreach statement. +/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. /// It rewrites: /// for ( type elem in collection) { stmts; } @@ -1070,6 +1074,54 @@ Stmt *RewriteTest::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S) { return 0; } +/// RewriteObjCSynchronizedStmt - +/// This routine rewrites @synchronized(expr) stmt; +/// into: +/// objc_sync_enter(expr); +/// @try stmt @finally { objc_sync_exit(expr); } +/// +Stmt *RewriteTest::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { + // Get the start location and compute the semi location. + SourceLocation startLoc = S->getLocStart(); + const char *startBuf = SM->getCharacterData(startLoc); + + assert((*startBuf == '@') && "bogus @synchronized location"); + + std::string buf; + buf = "objc_sync_enter"; + Rewrite.ReplaceText(startLoc, 13, buf.c_str(), buf.size()); + SourceLocation endLoc = S->getSynchExpr()->getLocEnd(); + const char *endBuf = SM->getCharacterData(endLoc); + endBuf++; + const char *rparenBuf = strchr(endBuf, ')'); + SourceLocation rparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf); + buf = ");\n"; + // declare a new scope with two variables, _stack and _rethrow. + buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; + buf += "int buf[18/*32-bit i386*/];\n"; + buf += "char *pointers[4];} _stack;\n"; + buf += "id volatile _rethrow = 0;\n"; + buf += "objc_exception_try_enter(&_stack);\n"; + buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; + Rewrite.ReplaceText(rparenLoc, 1, buf.c_str(), buf.size()); + startLoc = S->getSynchBody()->getLocEnd(); + startBuf = SM->getCharacterData(startLoc); + + assert((*startBuf == '}') && "bogus @try block"); + SourceLocation lastCurlyLoc = startLoc; + buf = "}\nelse {\n"; + buf += " _rethrow = objc_exception_extract(&_stack);\n"; + buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; + // FIXME: This must be objc_sync_exit(syncExpr); + buf += " objc_sync_exit();\n"; + buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; + buf += "}\n"; + buf += "}"; + + Rewrite.ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + return 0; +} + Stmt *RewriteTest::RewriteObjCTryStmt(ObjCAtTryStmt *S) { // Get the start location and compute the semi location. SourceLocation startLoc = S->getLocStart(); diff --git a/Sema/SemaStmt.cpp b/Sema/SemaStmt.cpp index e702ce802a..c84b3f344f 100644 --- a/Sema/SemaStmt.cpp +++ b/Sema/SemaStmt.cpp @@ -813,7 +813,7 @@ Action::StmtResult Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprTy *SynchExpr, StmtTy *SynchBody) { ObjCAtSynchronizedStmt *SS = new ObjCAtSynchronizedStmt(AtLoc, - static_cast(SynchExpr), static_cast(SynchBody)); + static_cast(SynchExpr), static_cast(SynchBody)); return SS; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 17757fb52d..7f41d0d287 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -966,25 +966,31 @@ public: /// class ObjCAtSynchronizedStmt : public Stmt { private: - Expr* SynchExpr; - Stmt* SynchBody; + enum { SYNC_EXPR, SYNC_BODY, END_EXPR }; + Stmt* SubStmts[END_EXPR]; SourceLocation AtSynchronizedLoc; public: - ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Expr *synchExpr, + ObjCAtSynchronizedStmt(SourceLocation atSynchronizedLoc, Stmt *synchExpr, Stmt *synchBody) - : Stmt(ObjCAtSynchronizedStmtClass), - SynchExpr(synchExpr), SynchBody(synchBody), - AtSynchronizedLoc(atSynchronizedLoc) {} + : Stmt(ObjCAtSynchronizedStmtClass) { + SubStmts[SYNC_EXPR] = synchExpr; + SubStmts[SYNC_BODY] = synchBody; + AtSynchronizedLoc = atSynchronizedLoc; + } - const Stmt *getSynchBody() const { return SynchBody; } - Stmt *getSynchBody() { return SynchBody; } + const Stmt *getSynchBody() const { return SubStmts[SYNC_BODY]; } + Stmt *getSynchBody() { return SubStmts[SYNC_BODY]; } - const Expr *getSynchExpr() const { return SynchExpr; } - Expr *getSynchExpr() { return SynchExpr; } + const Expr *getSynchExpr() const { + return reinterpret_cast(SubStmts[SYNC_EXPR]); + } + Expr *getSynchExpr() { + return reinterpret_cast(SubStmts[SYNC_EXPR]); + } virtual SourceRange getSourceRange() const { - return SourceRange(AtSynchronizedLoc, SynchBody->getLocEnd()); + return SourceRange(AtSynchronizedLoc, getSynchBody()->getLocEnd()); } static bool classof(const Stmt *T) { diff --git a/test/Sema/objc-synchronized-1.m b/test/Sema/objc-synchronized-1.m new file mode 100644 index 0000000000..cb65fc4832 --- /dev/null +++ b/test/Sema/objc-synchronized-1.m @@ -0,0 +1,16 @@ +// RUN: clang -rewrite-test %s | clang + +id SYNCH_EXPR(); +void SYNCH_BODY(); +void SYNCH_BEFORE(); +void SYNC_AFTER(); + +void foo(id sem) +{ + SYNCH_BEFORE(); + @synchronized (SYNCH_EXPR()) { + SYNCH_BODY(); + return; + } + SYNC_AFTER(); +}