]> granicus.if.org Git - clang/commitdiff
Refine noreturn handling. Fixes -Wmissing-noreturn so that it doesn't
authorMike Stump <mrs@apple.com>
Tue, 27 Oct 2009 01:59:05 +0000 (01:59 +0000)
committerMike Stump <mrs@apple.com>
Tue, 27 Oct 2009 01:59:05 +0000 (01:59 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/SemaObjC/return.m

index fa10dead6e3c46aaa8af7569b4201e33cdb45be3..f108878676c64131f4f5165c8b6b5bbcc909c3a6 100644 (file)
@@ -988,7 +988,7 @@ public:
   void CheckCXXDefaultArguments(FunctionDecl *FD);
   void CheckExtraCXXDefaultArguments(Declarator &D);
   enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1,
-                         AlwaysFallThrough = 2 };
+                         AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 };
   ControlFlowKind CheckFallThrough(Stmt *);
 
   Scope *getNonFieldDeclScope(Scope *S);
index 8277a6ad5bae582b17359feddaf51b78f6d906e5..886b8869c84b5b5f629083e17d10e6e6462ad8cd 100644 (file)
@@ -1044,6 +1044,7 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
 /// Statement that should return a value.
 ///
 /// \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
 /// NeverFallThrough iff we never fall off the end of the statement.  We assume
 /// 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.
   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
   // confuse us, so we mark all live things first.
   std::queue<CFGBlock*> workq;
@@ -1127,8 +1129,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) {
     if (NoReturnEdge == false)
       HasPlainEdge = true;
   }
-  if (!HasPlainEdge)
-    return NeverFallThrough;
+  if (!HasPlainEdge) {
+    if (HasLiveReturn)
+      return NeverFallThrough;
+    return NeverFallThroughOrReturn;
+  }
   if (HasFakeEdge || HasLiveReturn)
     return MaybeFallThrough;
   // 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)
         Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function);
       break;
-    case NeverFallThrough:
+    case NeverFallThroughOrReturn:
       if (ReturnsVoid && !HasNoReturn)
         Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function);
       break;
+    case NeverFallThrough:
+      break;
     }
   }
 }
@@ -1243,10 +1250,12 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) {
       else if (!ReturnsVoid)
         Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block);
       break;
-    case NeverFallThrough:
+    case NeverFallThroughOrReturn:
       if (ReturnsVoid)
         Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block);
       break;
+    case NeverFallThrough:
+      break;
     }
   }
 }
index 9acf470799580edb4d218bb48eeb64b0d4ab6ace..ff64994794581e2f7dad0f364d0253b7c7cd6879 100644 (file)
@@ -1,6 +1,22 @@
-// RUN: clang-cc %s -fsyntax-only -verify
+// RUN: clang-cc %s -fsyntax-only -verify -Wmissing-noreturn
 
 int test1() {
   id 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;
+  }
+}