]> granicus.if.org Git - clang/commitdiff
modern objective-c translator: writing @try/@finally statement.
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 15 Mar 2012 22:42:15 +0000 (22:42 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 15 Mar 2012 22:42:15 +0000 (22:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152867 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Rewrite/RewriteModernObjC.cpp
test/Rewriter/rewrite-modern-try-finally.m [new file with mode: 0644]

index 864ecdfe45c924c0aa739063b26bfcc57b1dfc47..74745204a495d567c0c3f7275749d948be625fa2 100644 (file)
@@ -1835,13 +1835,41 @@ void RewriteModernObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf)
 }
 
 Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
+  ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();
+  // bool noCatch = S->getNumCatchStmts() == 0;
+  std::string buf;
+  
+  if (finalStmt) {
+    buf = "{ id volatile _rethrow = 0;\n";
+  }
   // Get the start location and compute the semi location.
   SourceLocation startLoc = S->getLocStart();
   const char *startBuf = SM->getCharacterData(startLoc);
 
   assert((*startBuf == '@') && "bogus @try location");
-  // @try -> try
-  ReplaceText(startLoc, 1, "");
+  if (finalStmt)
+    ReplaceText(startLoc, 1, buf);
+  else
+    // @try -> try
+    ReplaceText(startLoc, 1, "");
+  
+  if (finalStmt) {
+    buf.clear();
+    buf = "catch (id e) {_rethrow = e;}\n";
+    SourceLocation startFinalLoc = finalStmt->getLocStart();
+    ReplaceText(startFinalLoc, 8, buf);
+    Stmt *body = finalStmt->getFinallyBody();
+    SourceLocation startFinalBodyLoc = body->getLocStart();
+    buf.clear();
+    buf = "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";
+    buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";
+    buf += "\tid rethrow;\n";
+    buf += "\t} _fin_force_rethow(_rethrow);";
+    ReplaceText(startFinalBodyLoc, 1, buf);
+    
+    SourceLocation endFinalBodyLoc = body->getLocEnd();
+    ReplaceText(endFinalBodyLoc, 1, "}\n}");
+  }
 
   for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
     ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
@@ -5144,7 +5172,7 @@ void RewriteModernObjC::Initialize(ASTContext &context) {
   Preamble += "(struct objc_class *);\n";
   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
   Preamble += "(const char *);\n";
-  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
+  Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(id);\n";
   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
diff --git a/test/Rewriter/rewrite-modern-try-finally.m b/test/Rewriter/rewrite-modern-try-finally.m
new file mode 100644 (file)
index 0000000..cf342d7
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -x objective-c -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -fexceptions  -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+
+void FINALLY();
+void TRY();
+void INNER_FINALLY();
+void INNER_TRY();
+void CHECK();
+
+@interface Foo
+@end
+
+@implementation Foo
+- (void)bar {
+    @try {
+       TRY();
+    } 
+    @finally {
+       FINALLY();
+    }
+    CHECK();
+    @try {
+       TRY();
+    } 
+    @finally {
+      @try {
+        INNER_TRY();
+      }
+      @finally {
+        INNER_FINALLY();
+      }
+      FINALLY();
+    }
+}
+@end