summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/Sema/Sema.h2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp5
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp21
-rw-r--r--clang/test/SemaCXX/exceptions.cpp29
-rw-r--r--clang/www/cxx_status.html2
6 files changed, 60 insertions, 1 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c6f3b0b50b1..e115703a95e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1204,6 +1204,8 @@ def err_throw_incomplete : Error<
"cannot throw object of incomplete type %0">;
def err_throw_incomplete_ptr : Error<
"cannot throw pointer to object of incomplete type %0">;
+def err_return_in_constructor_handler : Error<
+ "return in the catch of a function try block of a constructor is illegal">;
def err_invalid_use_of_function_type : Error<
"a function type is not allowed here">;
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 637804ce092..faaeb7989e5 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -60,6 +60,7 @@ namespace clang {
class ArrayType;
class LabelStmt;
class SwitchStmt;
+ class CXXTryStmt;
class ExtVectorType;
class TypedefDecl;
class TemplateDecl;
@@ -1225,6 +1226,7 @@ public:
virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
StmtArg TryBlock,
MultiStmtArg Handlers);
+ void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 482c304603b..7549c9c69cf 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3054,6 +3054,11 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) {
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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 87a518b5583..71d2f80cfc4 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2664,3 +2664,24 @@ void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
}
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);
+ }
+}
diff --git a/clang/test/SemaCXX/exceptions.cpp b/clang/test/SemaCXX/exceptions.cpp
index 42973eba70e..5882b9cb708 100644
--- a/clang/test/SemaCXX/exceptions.cpp
+++ b/clang/test/SemaCXX/exceptions.cpp
@@ -68,3 +68,32 @@ l5:
goto l2; // expected-error {{illegal goto into protected scope}}
goto l1;
}
+
+struct BadReturn {
+ BadReturn() try {
+ } catch(...) {
+ // Try to hide
+ try {
+ } catch(...) {
+ {
+ if (0)
+ return; // expected-error {{return in the catch of a function try block of a constructor is illegal}}
+ }
+ }
+ }
+ BadReturn(int);
+};
+
+BadReturn::BadReturn(int) try {
+} catch(...) {
+ // Try to hide
+ try {
+ } catch(int) {
+ return; // expected-error {{return in the catch of a function try block of a constructor is illegal}}
+ } catch(...) {
+ {
+ if (0)
+ return; // expected-error {{return in the catch of a function try block of a constructor is illegal}}
+ }
+ }
+}
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index ab8171c4cf3..e8547cd6bb4 100644
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1664,7 +1664,7 @@ welcome!</p>
<td class="na" align="center">N/A</td>
<td class="advanced" align="center"></td>
<td></td>
- <td>Not all constraints are checked, such as existence of return statements in function-try-block handlers of constructors</td>
+ <td>Not all constraints are checked</td>
</tr>
<tr>
<td>&nbsp;&nbsp;15.4 [except.spec]</td>
OpenPOWER on IntegriCloud