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
diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp
index d253654..cf26b6e 100644
--- a/lib/Frontend/PCHReaderStmt.cpp
+++ b/lib/Frontend/PCHReaderStmt.cpp
@@ -838,12 +838,11 @@
 
 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::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 @@
       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);