зеркало из https://github.com/microsoft/clang.git
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
This commit is contained in:
Родитель
2bf1eb09f0
Коммит
13e8854b18
|
@ -1204,6 +1204,8 @@ def err_throw_incomplete : Error<
|
||||||
"cannot throw object of incomplete type %0">;
|
"cannot throw object of incomplete type %0">;
|
||||||
def err_throw_incomplete_ptr : Error<
|
def err_throw_incomplete_ptr : Error<
|
||||||
"cannot throw pointer to object of incomplete type %0">;
|
"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<
|
def err_invalid_use_of_function_type : Error<
|
||||||
"a function type is not allowed here">;
|
"a function type is not allowed here">;
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace clang {
|
||||||
class ArrayType;
|
class ArrayType;
|
||||||
class LabelStmt;
|
class LabelStmt;
|
||||||
class SwitchStmt;
|
class SwitchStmt;
|
||||||
|
class CXXTryStmt;
|
||||||
class ExtVectorType;
|
class ExtVectorType;
|
||||||
class TypedefDecl;
|
class TypedefDecl;
|
||||||
class TemplateDecl;
|
class TemplateDecl;
|
||||||
|
@ -1225,6 +1226,7 @@ public:
|
||||||
virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
|
virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
|
||||||
StmtArg TryBlock,
|
StmtArg TryBlock,
|
||||||
MultiStmtArg Handlers);
|
MultiStmtArg Handlers);
|
||||||
|
void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock);
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Expression Parsing Callbacks: SemaExpr.cpp.
|
// Expression Parsing Callbacks: SemaExpr.cpp.
|
||||||
|
|
|
@ -3054,6 +3054,11 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) {
|
||||||
if (CurFunctionNeedsScopeChecking)
|
if (CurFunctionNeedsScopeChecking)
|
||||||
DiagnoseInvalidJumps(Body);
|
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;
|
return D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2664,3 +2664,24 @@ void Sema::SetDeclDeleted(DeclPtrTy dcl, SourceLocation DelLoc) {
|
||||||
}
|
}
|
||||||
Fn->setDeleted();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -68,3 +68,32 @@ l5:
|
||||||
goto l2; // expected-error {{illegal goto into protected scope}}
|
goto l2; // expected-error {{illegal goto into protected scope}}
|
||||||
goto l1;
|
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}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1664,7 +1664,7 @@ welcome!</p>
|
||||||
<td class="na" align="center">N/A</td>
|
<td class="na" align="center">N/A</td>
|
||||||
<td class="advanced" align="center"></td>
|
<td class="advanced" align="center"></td>
|
||||||
<td></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>
|
||||||
<tr>
|
<tr>
|
||||||
<td> 15.4 [except.spec]</td>
|
<td> 15.4 [except.spec]</td>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче