Full AST support and better Sema support for C++ try-catch.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61346 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index c179fe8..48af5af 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -640,9 +640,9 @@
   virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
                                               DeclTy *ExDecl,
                                               StmtArg HandlerBlock);
-  //virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
-  //                                          StmtArg TryBlock,
-  //                                          MultiStmtArg Handlers);
+  virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+                                            StmtArg TryBlock,
+                                            MultiStmtArg Handlers);
 
   //===--------------------------------------------------------------------===//
   // Expression Parsing Callbacks: SemaExpr.cpp.
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4ac7ecb..8a37bbb 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2058,6 +2058,10 @@
     Diag(Begin, diag::err_catch_incomplete) << BaseType << Mode;
   }
 
+  // FIXME: Need to test for ability to copy-construct and destroy the
+  // exception variable.
+  // FIXME: Need to check for abstract classes.
+
   IdentifierInfo *II = D.getIdentifier();
   if (Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S)) {
     // The scope should be freshly made just for us. There is just no way
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 6a322ee..0c441f7 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -961,3 +961,31 @@
   return Owned(new CXXCatchStmt(CatchLoc, static_cast<VarDecl*>(ExDecl),
                                 static_cast<Stmt*>(HandlerBlock.release())));
 }
+
+/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
+/// handlers and creates a try statement from them.
+Action::OwningStmtResult
+Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
+                       MultiStmtArg RawHandlers) {
+  unsigned NumHandlers = RawHandlers.size();
+  assert(NumHandlers > 0 &&
+         "The parser shouldn't call this if there are no handlers.");
+  Stmt **Handlers = reinterpret_cast<Stmt**>(RawHandlers.get());
+
+  for(unsigned i = 0; i < NumHandlers - 1; ++i) {
+    CXXCatchStmt *Handler = llvm::cast<CXXCatchStmt>(Handlers[i]);
+    if (!Handler->getExceptionDecl())
+      return StmtError(Diag(Handler->getLocStart(), diag::err_early_catch_all));
+  }
+  // FIXME: We should detect handlers for the same type as an earlier one.
+  // This one is rather easy.
+  // FIXME: We should detect handlers that cannot catch anything because an
+  // earlier handler catches a superclass. Need to find a method that is not
+  // quadratic for this.
+  // Neither of these are explicitly forbidden, but every compiler detects them
+  // and warns.
+
+  RawHandlers.release();
+  return Owned(new CXXTryStmt(TryLoc, static_cast<Stmt*>(TryBlock.release()),
+                              Handlers, NumHandlers));
+}