]> granicus.if.org Git - clang/commitdiff
Rewriting of @synchronized. This has one FIXME in it. But this should allow @sychroni...
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 29 Jan 2008 22:59:37 +0000 (22:59 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 29 Jan 2008 22:59:37 +0000 (22:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46533 91177308-0d34-0410-b5e6-96231b3b80d8

AST/Stmt.cpp
AST/StmtSerialization.cpp
Driver/RewriteTest.cpp
Sema/SemaStmt.cpp
include/clang/AST/Stmt.h
test/Sema/objc-synchronized-1.m [new file with mode: 0644]

index 0f4936b1bbf056eba1d0f6f4406c21ab8289fd35..4d1be5539d4dfd19b61e9ed86ebadb699d9bac3c 100644 (file)
@@ -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;
 }
 
index 8e743e6cb7e135e95572387099c4ab248d94b9c5..227f365e1cc6e87227aa0efcf300362f84a3b3bd 100644 (file)
@@ -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;
 }
 
index 0bcef9547689c018e267263737177ccc167ba785..aac572177a864d1254b12e37465566eeb787221f 100644 (file)
@@ -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<ObjCAtTryStmt>(S))
     return RewriteObjCTryStmt(StmtTry);
 
+  if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
+    return RewriteObjCSynchronizedStmt(StmtTry);
+
   if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(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();
index e702ce802a38aa8627c79d669a5afaf86fa7bd23..c84b3f344f3f38e253b39ff1c272dcc888dee2ef 100644 (file)
@@ -813,7 +813,7 @@ Action::StmtResult
 Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, ExprTy *SynchExpr, 
                                   StmtTy *SynchBody) {
   ObjCAtSynchronizedStmt *SS = new ObjCAtSynchronizedStmt(AtLoc, 
-    static_cast<Expr*>(SynchExpr), static_cast<Stmt*>(SynchBody));
+    static_cast<Stmt*>(SynchExpr), static_cast<Stmt*>(SynchBody));
   return SS;
 }
 
index 17757fb52d91f83be6aaed9a1c791139a8326fd6..7f41d0d287d156f5411921a287b3cc9e9082cf69 100644 (file)
@@ -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<Expr*>(SubStmts[SYNC_EXPR]); 
+  }
+  Expr *getSynchExpr() { 
+    return reinterpret_cast<Expr*>(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 (file)
index 0000000..cb65fc4
--- /dev/null
@@ -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();
+}