diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-23 22:50:49 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-23 22:50:49 +0000 |
commit | 8f5e3dd32e443768d9dbbad7191e123e6733750c (patch) | |
tree | 91499ffda788228d2b75b1780257b5e7fce81f4c /lib/Frontend | |
parent | ec951e0c2fc0db00c36bc60c900331dde32c1b43 (diff) |
Improve the AST representation of Objective-C @try/@catch/@finally
statements. Instead of the @try having a single @catch, where all of
the @catch's were chained (using an O(n^2) algorithm nonetheless),
@try just holds an array of its @catch blocks. The resulting AST is
slightly more compact (not important) and better represents the actual
language semantics (good).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102221 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Frontend')
-rw-r--r-- | lib/Frontend/PCHReaderStmt.cpp | 27 | ||||
-rw-r--r-- | lib/Frontend/PCHWriterStmt.cpp | 9 | ||||
-rw-r--r-- | lib/Frontend/RewriteObjC.cpp | 24 |
3 files changed, 36 insertions, 24 deletions
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index d253654f7c..cf26b6e237 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -838,12 +838,11 @@ unsigned PCHStmtReader::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { unsigned PCHStmtReader::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { VisitStmt(S); - S->setCatchBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2])); - S->setNextCatchStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1])); + S->setCatchBody(cast_or_null<Stmt>(StmtStack.back())); S->setCatchParamDecl(cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); S->setAtCatchLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); S->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - return 2; + return 1; } unsigned PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { @@ -855,11 +854,21 @@ unsigned PCHStmtReader::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { unsigned PCHStmtReader::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { VisitStmt(S); - S->setTryBody(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 3])); - S->setCatchStmts(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 2])); - S->setFinallyStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1])); + assert(Record[Idx] == S->getNumCatchStmts()); + ++Idx; + bool HasFinally = Record[Idx++]; + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { + unsigned Offset = StmtStack.size() - N - HasFinally + I; + S->setCatchStmt(I, cast_or_null<ObjCAtCatchStmt>(StmtStack[Offset])); + } + + unsigned TryOffset + = StmtStack.size() - S->getNumCatchStmts() - HasFinally - 1; + S->setTryBody(cast_or_null<Stmt>(StmtStack[TryOffset])); + if (HasFinally) + S->setFinallyStmt(cast_or_null<Stmt>(StmtStack[StmtStack.size() - 1])); S->setAtTryLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - return 3; + return 1 + S->getNumCatchStmts() + HasFinally; } unsigned PCHStmtReader::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S) { @@ -1231,7 +1240,9 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { S = new (Context) ObjCAtFinallyStmt(Empty); break; case pch::STMT_OBJC_AT_TRY: - S = new (Context) ObjCAtTryStmt(Empty); + S = ObjCAtTryStmt::CreateEmpty(*Context, + Record[PCHStmtReader::NumStmtFields], + Record[PCHStmtReader::NumStmtFields + 1]); break; case pch::STMT_OBJC_AT_SYNCHRONIZED: S = new (Context) ObjCAtSynchronizedStmt(Empty); diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 9a9539bb54..a0ea5c9553 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -764,7 +764,6 @@ void PCHStmtWriter::VisitObjCForCollectionStmt(ObjCForCollectionStmt *S) { void PCHStmtWriter::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { Writer.WriteSubStmt(S->getCatchBody()); - Writer.WriteSubStmt(S->getNextCatchStmt()); Writer.AddDeclRef(S->getCatchParamDecl(), Record); Writer.AddSourceLocation(S->getAtCatchLoc(), Record); Writer.AddSourceLocation(S->getRParenLoc(), Record); @@ -778,9 +777,13 @@ void PCHStmtWriter::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { } void PCHStmtWriter::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { + Record.push_back(S->getNumCatchStmts()); + Record.push_back(S->getFinallyStmt() != 0); Writer.WriteSubStmt(S->getTryBody()); - Writer.WriteSubStmt(S->getCatchStmts()); - Writer.WriteSubStmt(S->getFinallyStmt()); + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) + Writer.WriteSubStmt(S->getCatchStmt(I)); + if (S->getFinallyStmt()) + Writer.WriteSubStmt(S->getFinallyStmt()); Writer.AddSourceLocation(S->getAtTryLoc(), Record); Code = pch::STMT_OBJC_AT_TRY; } diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index 66b8d39c70..fc674354c4 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -1861,8 +1861,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { assert((*startBuf == '}') && "bogus @try block"); SourceLocation lastCurlyLoc = startLoc; - ObjCAtCatchStmt *catchList = S->getCatchStmts(); - if (catchList) { + if (S->getNumCatchStmts()) { startLoc = startLoc.getFileLocWithOffset(1); buf = " /* @catch begin */ else {\n"; buf += " id _caught = objc_exception_extract(&_stack);\n"; @@ -1880,26 +1879,27 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } bool sawIdTypedCatch = false; Stmt *lastCatchBody = 0; - while (catchList) { - ParmVarDecl *catchDecl = catchList->getCatchParamDecl(); + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { + ObjCAtCatchStmt *Catch = S->getCatchStmt(I); + ParmVarDecl *catchDecl = Catch->getCatchParamDecl(); - if (catchList == S->getCatchStmts()) + if (I == 0) buf = "if ("; // we are generating code for the first catch clause else buf = "else if ("; - startLoc = catchList->getLocStart(); + startLoc = Catch->getLocStart(); startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @catch location"); const char *lParenLoc = strchr(startBuf, '('); - if (catchList->hasEllipsis()) { + if (Catch->hasEllipsis()) { // Now rewrite the body... - lastCatchBody = catchList->getCatchBody(); + lastCatchBody = Catch->getCatchBody(); SourceLocation bodyLoc = lastCatchBody->getLocStart(); const char *bodyBuf = SM->getCharacterData(bodyLoc); - assert(*SM->getCharacterData(catchList->getRParenLoc()) == ')' && + assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && "bogus @catch paren location"); assert((*bodyBuf == '{') && "bogus @catch body location"); @@ -1923,8 +1923,8 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } } // Now rewrite the body... - lastCatchBody = catchList->getCatchBody(); - SourceLocation rParenLoc = catchList->getRParenLoc(); + lastCatchBody = Catch->getCatchBody(); + SourceLocation rParenLoc = Catch->getRParenLoc(); SourceLocation bodyLoc = lastCatchBody->getLocStart(); const char *bodyBuf = SM->getCharacterData(bodyLoc); const char *rParenBuf = SM->getCharacterData(rParenLoc); @@ -1937,8 +1937,6 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } else { assert(false && "@catch rewrite bug"); } - // make sure all the catch bodies get rewritten! - catchList = catchList->getNextCatchStmt(); } // Complete the catch list... if (lastCatchBody) { |