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:
Mike Stump 2009-10-27 01:59:05 +00:00
Родитель 848b9b6227
Коммит 1d7e767dc8
3 изменённых файлов: 32 добавлений и 7 удалений

Просмотреть файл

@ -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;
}
}