aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-07-28 23:11:12 +0000
committerMike Stump <mrs@apple.com>2009-07-28 23:11:12 +0000
commit4d9d51ae3b868268082f94d84d0dff4c0b1ad435 (patch)
tree38a33bbab8bc8849dd068c4a324509d2fbd5ee50
parent1275ae098acda31fe0e434510c729fcfed0458a1 (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.td6
-rw-r--r--lib/Sema/SemaDecl.cpp15
-rw-r--r--test/Sema/return-noreturn.c12
-rw-r--r--test/Sema/return.c10
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) { }
+}