diff options
author | Mike Stump <mrs@apple.com> | 2009-07-28 23:11:12 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2009-07-28 23:11:12 +0000 |
commit | 4d9d51ae3b868268082f94d84d0dff4c0b1ad435 (patch) | |
tree | 38a33bbab8bc8849dd068c4a324509d2fbd5ee50 | |
parent | 1275ae098acda31fe0e434510c729fcfed0458a1 (diff) |
Add support for -Wmissing-noreturn.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77391 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 15 | ||||
-rw-r--r-- | test/Sema/return-noreturn.c | 12 | ||||
-rw-r--r-- | test/Sema/return.c | 10 |
4 files changed, 41 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 65f0488072..5129fc8cdb 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -114,6 +114,12 @@ def err_maybe_falloff_nonvoid_block : Error< "control may reach end of non-void block">; def err_falloff_nonvoid_block : Error< "control reaches end of non-void block">; +def warn_suggest_noreturn_function : Warning< + "function could be attribute 'noreturn'">, + InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore; +def warn_suggest_noreturn_block : Warning< + "block could be attribute 'noreturn'">, + InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore; /// Built-in functions. def ext_implicit_lib_function_decl : ExtWarn< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7c0f849fd7..c6fb6d97bd 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1149,10 +1149,13 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) { HasNoReturn = true; } + // Short circuit for compilation speed. if ((Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function) == Diagnostic::Ignored || ReturnsVoid) && (Diags.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr) - == Diagnostic::Ignored || !HasNoReturn)) + == Diagnostic::Ignored || !HasNoReturn) + && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block) + == Diagnostic::Ignored || !ReturnsVoid)) return; // FIXME: Funtion try block if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { @@ -1170,6 +1173,8 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) { Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function); break; case NeverFallThrough: + if (ReturnsVoid) + Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function); break; } } @@ -1197,7 +1202,11 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) { HasNoReturn = true; } - if (ReturnsVoid && !HasNoReturn) + // Short circuit for compilation speed. + if (ReturnsVoid + && !HasNoReturn + && (Diags.getDiagnosticLevel(diag::warn_suggest_noreturn_block) + == Diagnostic::Ignored || !ReturnsVoid)) return; // FIXME: Funtion try block if (CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { @@ -1215,6 +1224,8 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) { Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block); break; case NeverFallThrough: + if (ReturnsVoid) + Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block); break; } } diff --git a/test/Sema/return-noreturn.c b/test/Sema/return-noreturn.c new file mode 100644 index 0000000000..c1cebee864 --- /dev/null +++ b/test/Sema/return-noreturn.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -fsyntax-only -verify -Wmissing-noreturn + +int j; +void test1() { // expected-warning {{function could be attribute 'noreturn'}} + ^ (void) { while (1) { } }(); // expected-warning {{block could be attribute 'noreturn'}} + ^ (void) { if (j) while (1) { } }(); + while (1) { } +} + +void test2() { + if (j) while (1) { } +} diff --git a/test/Sema/return.c b/test/Sema/return.c index 423d1a9902..3c5fc79ebd 100644 --- a/test/Sema/return.c +++ b/test/Sema/return.c @@ -208,3 +208,13 @@ int test30() { typedef void test31_t(int status); void test31(test31_t *callback __attribute__((noreturn))); + +void test32() { + ^ (void) { while (1) { } }(); + ^ (void) { if (j) while (1) { } }(); + while (1) { } +} + +void test33() { + if (j) while (1) { } +} |