From 4c14881e86350c8aa12d5182d35ce07860de2325 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 15 Mar 2012 20:11:10 +0000 Subject: [PATCH] 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 --- lib/Rewrite/RewriteModernObjC.cpp | 41 +++++++++++++++++++++++++--- test/Rewriter/rewrite-modern-catch.m | 31 +++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 test/Rewriter/rewrite-modern-catch.m 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()) { + // 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 -- 2.40.0