зеркало из https://github.com/microsoft/clang-1.git
Refine noreturn handling. Fixes -Wmissing-noreturn so that it doesn't
complain that functions that have a return statement should be declared noreturn. Fixed PR5286. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85195 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
848b9b6227
Коммит
1d7e767dc8
|
@ -988,7 +988,7 @@ public:
|
||||||
void CheckCXXDefaultArguments(FunctionDecl *FD);
|
void CheckCXXDefaultArguments(FunctionDecl *FD);
|
||||||
void CheckExtraCXXDefaultArguments(Declarator &D);
|
void CheckExtraCXXDefaultArguments(Declarator &D);
|
||||||
enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1,
|
enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1,
|
||||||
AlwaysFallThrough = 2 };
|
AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 };
|
||||||
ControlFlowKind CheckFallThrough(Stmt *);
|
ControlFlowKind CheckFallThrough(Stmt *);
|
||||||
|
|
||||||
Scope *getNonFieldDeclScope(Scope *S);
|
Scope *getNonFieldDeclScope(Scope *S);
|
||||||
|
|
|
@ -1044,6 +1044,7 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
|
||||||
/// Statement that should return a value.
|
/// Statement that should return a value.
|
||||||
///
|
///
|
||||||
/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
|
/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
|
||||||
|
/// MaybeFallThroughOrReturn iff we might or might not fall off the end and
|
||||||
/// MaybeFallThrough iff we might or might not fall off the end and
|
/// MaybeFallThrough iff we might or might not fall off the end and
|
||||||
/// NeverFallThrough iff we never fall off the end of the statement. We assume
|
/// NeverFallThrough iff we never fall off the end of the statement. We assume
|
||||||
/// that functions not marked noreturn will return.
|
/// that functions not marked noreturn will return.
|
||||||
|
@ -1054,7 +1055,8 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
|
||||||
|
|
||||||
// FIXME: They should never return 0, fix that, delete this code.
|
// FIXME: They should never return 0, fix that, delete this code.
|
||||||
if (cfg == 0)
|
if (cfg == 0)
|
||||||
return NeverFallThrough;
|
// FIXME: This should be NeverFallThrough
|
||||||
|
return NeverFallThroughOrReturn;
|
||||||
// The CFG leaves in dead things, and we don't want to dead code paths to
|
// The CFG leaves in dead things, and we don't want to dead code paths to
|
||||||
// confuse us, so we mark all live things first.
|
// confuse us, so we mark all live things first.
|
||||||
std::queue<CFGBlock*> workq;
|
std::queue<CFGBlock*> workq;
|
||||||
|
@ -1127,8 +1129,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
|
||||||
if (NoReturnEdge == false)
|
if (NoReturnEdge == false)
|
||||||
HasPlainEdge = true;
|
HasPlainEdge = true;
|
||||||
}
|
}
|
||||||
if (!HasPlainEdge)
|
if (!HasPlainEdge) {
|
||||||
return NeverFallThrough;
|
if (HasLiveReturn)
|
||||||
|
return NeverFallThrough;
|
||||||
|
return NeverFallThroughOrReturn;
|
||||||
|
}
|
||||||
if (HasFakeEdge || HasLiveReturn)
|
if (HasFakeEdge || HasLiveReturn)
|
||||||
return MaybeFallThrough;
|
return MaybeFallThrough;
|
||||||
// This says AlwaysFallThrough for calls to functions that are not marked
|
// This says AlwaysFallThrough for calls to functions that are not marked
|
||||||
|
@ -1192,10 +1197,12 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
|
||||||
else if (!ReturnsVoid)
|
else if (!ReturnsVoid)
|
||||||
Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
|
Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
|
||||||
break;
|
break;
|
||||||
case NeverFallThrough:
|
case NeverFallThroughOrReturn:
|
||||||
if (ReturnsVoid && !HasNoReturn)
|
if (ReturnsVoid && !HasNoReturn)
|
||||||
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
|
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
|
||||||
break;
|
break;
|
||||||
|
case NeverFallThrough:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1243,10 +1250,12 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
|
||||||
else if (!ReturnsVoid)
|
else if (!ReturnsVoid)
|
||||||
Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
|
Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
|
||||||
break;
|
break;
|
||||||
case NeverFallThrough:
|
case NeverFallThroughOrReturn:
|
||||||
if (ReturnsVoid)
|
if (ReturnsVoid)
|
||||||
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
|
Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
|
||||||
break;
|
break;
|
||||||
|
case NeverFallThrough:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
// RUN: clang-cc %s -fsyntax-only -verify
|
// RUN: clang-cc %s -fsyntax-only -verify -Wmissing-noreturn
|
||||||
|
|
||||||
int test1() {
|
int test1() {
|
||||||
id a;
|
id a;
|
||||||
@throw a;
|
@throw a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PR5286
|
||||||
|
void test2(int a) {
|
||||||
|
while (1) {
|
||||||
|
if (a)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PR5286
|
||||||
|
void test3(int a) { // expected-warning {{function could be attribute 'noreturn'}}
|
||||||
|
while (1) {
|
||||||
|
if (a)
|
||||||
|
@throw (id)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче