modern objective-c translator: writing @try/@finally statement.

llvm-svn: 152867
This commit is contained in:
Fariborz Jahanian 2012-03-15 22:42:15 +00:00
parent 9c76d24f9c
commit 3b71b17753
2 changed files with 66 additions and 3 deletions

View 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";

View File

@ -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