aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2012-03-15 20:11:10 +0000
committerFariborz Jahanian <fjahanian@apple.com>2012-03-15 20:11:10 +0000
commit4c14881e86350c8aa12d5182d35ce07860de2325 (patch)
tree17fb8d62428f2a3ea0a11181196b87bf739f2cf2
parent0f5897bf5f919df28c76013d1efa17441f7241ff (diff)
modern objective-c translator: rewriting of @catch-stmt.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152830 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Rewrite/RewriteModernObjC.cpp41
-rw-r--r--test/Rewriter/rewrite-modern-catch.m31
2 files changed, 68 insertions, 4 deletions
diff --git a/lib/Rewrite/RewriteModernObjC.cpp b/lib/Rewrite/RewriteModernObjC.cpp
index c9d4158286..864ecdfe45 100644
--- a/lib/Rewrite/RewriteModernObjC.cpp
+++ b/lib/Rewrite/RewriteModernObjC.cpp
@@ -1845,12 +1845,45 @@ Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
+ VarDecl *catchDecl = Catch->getCatchParamDecl();
startLoc = Catch->getLocStart();
- startBuf = SM->getCharacterData(startLoc);
- assert((*startBuf == '@') && "bogus @catch location");
- // @catch -> catch
- ReplaceText(startLoc, 1, "");
+ bool AtRemoved = false;
+ if (catchDecl) {
+ QualType t = catchDecl->getType();
+ if (const ObjCObjectPointerType *Ptr = t->getAs<ObjCObjectPointerType>()) {
+ // Should be a pointer to a class.
+ ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
+ if (IDecl) {
+ std::string Result;
+ startBuf = SM->getCharacterData(startLoc);
+ assert((*startBuf == '@') && "bogus @catch location");
+ SourceLocation rParenLoc = Catch->getRParenLoc();
+ const char *rParenBuf = SM->getCharacterData(rParenLoc);
+
+ // _objc_exc_Foo *_e as argument to catch.
+ Result = "catch (_objc_exc_"; Result += IDecl->getNameAsString();
+ Result += " *_"; Result += catchDecl->getNameAsString();
+ Result += ")";
+ ReplaceText(startLoc, rParenBuf-startBuf+1, Result);
+ // Foo *e = (Foo *)_e;
+ Result.clear();
+ Result = "{ ";
+ Result += IDecl->getNameAsString();
+ Result += " *"; Result += catchDecl->getNameAsString();
+ Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";
+ Result += "_"; Result += catchDecl->getNameAsString();
+
+ Result += "; ";
+ SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart();
+ ReplaceText(lBraceLoc, 1, Result);
+ AtRemoved = true;
+ }
+ }
+ }
+ if (!AtRemoved)
+ // @catch -> catch
+ ReplaceText(startLoc, 1, "");
}
return 0;
diff --git a/test/Rewriter/rewrite-modern-catch.m b/test/Rewriter/rewrite-modern-catch.m
new file mode 100644
index 0000000000..1900301e91
--- /dev/null
+++ b/test/Rewriter/rewrite-modern-catch.m
@@ -0,0 +1,31 @@
+// 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 foo(id arg);
+
+@interface NSException
+@end
+
+@interface Foo
+@end
+
+@implementation Foo
+- (void)bar {
+ @try {
+ } @catch (NSException *e) {
+ foo(e);
+ }
+ @catch (Foo *f) {
+ }
+ @catch (...) {
+ @try {
+ }
+ @catch (Foo *f1) {
+ foo(f1);
+ }
+ @catch (id pid) {
+ foo(pid);
+ }
+ }
+}
+@end