Track down return statements in the handlers of a function-try-block of constructors. Meh ...

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70256 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 637804c..faaeb79 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -60,6 +60,7 @@
   class ArrayType;
   class LabelStmt;
   class SwitchStmt;
+  class CXXTryStmt;
   class ExtVectorType;
   class TypedefDecl;
   class TemplateDecl;
@@ -1225,6 +1226,7 @@
   virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
                                             StmtArg TryBlock,
                                             MultiStmtArg Handlers);
+  void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
 
   //===--------------------------------------------------------------------===//
   // Expression Parsing Callbacks: SemaExpr.cpp.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 482c304..7549c9c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3054,6 +3054,11 @@
   if (CurFunctionNeedsScopeChecking)
     DiagnoseInvalidJumps(Body);
 
+  // C++ constructors that have function-try-blocks can't have return statements
+  // in the handlers of that block. (C++ [except.handle]p14) Verify this.
+  if (isa<CXXConstructorDecl>(dcl) && isa<CXXTryStmt>(Body))
+    DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(Body));
+
   return D;
 }
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 87a518b..71d2f80 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2664,3 +2664,24 @@
   }
   Fn->setDeleted();
 }
+
+static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
+  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
+       ++CI) {
+    Stmt *SubStmt = *CI;
+    if (!SubStmt)
+      continue;
+    if (isa<ReturnStmt>(SubStmt))
+      Self.Diag(SubStmt->getSourceRange().getBegin(),
+           diag::err_return_in_constructor_handler);
+    if (!isa<Expr>(SubStmt))
+      SearchForReturnInStmt(Self, SubStmt);
+  }
+}
+
+void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
+  for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
+    CXXCatchStmt *Handler = TryBlock->getHandler(I);
+    SearchForReturnInStmt(*this, Handler);
+  }
+}