]> granicus.if.org Git - clang/commitdiff
Add support for -Wmissing-noreturn.
authorMike Stump <mrs@apple.com>
Tue, 28 Jul 2009 23:11:12 +0000 (23:11 +0000)
committerMike Stump <mrs@apple.com>
Tue, 28 Jul 2009 23:11:12 +0000 (23:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77391 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/Sema/return-noreturn.c [new file with mode: 0644]
test/Sema/return.c

index 65f048807256e432495d791849625b97e0080e7e..5129fc8cdbf3aea025bbd7038494e854b164a12a 100644 (file)
@@ -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<
index 7c0f849fd7555fe143b1f4a7b7f42bb797226607..c6fb6d97bdf6e0226e7aaed50a3b9662140caf2f 100644 (file)
@@ -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 (file)
index 0000000..c1cebee
--- /dev/null
@@ -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) { }
+}
index 423d1a9902959eeef7eda6495ee152236535428a..3c5fc79ebdd1e03c31299c3b40e9b124f0009004 100644 (file)
@@ -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) { }
+}