diff options
-rw-r--r-- | lib/Sema/Sema.h | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 19 | ||||
-rw-r--r-- | test/SemaObjC/return.m | 18 |
3 files changed, 32 insertions, 7 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index fa10dead6e..f108878676 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8277a6ad5b..886b8869c8 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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; } } } diff --git a/test/SemaObjC/return.m b/test/SemaObjC/return.m index 9acf470799..ff64994794 100644 --- a/test/SemaObjC/return.m +++ b/test/SemaObjC/return.m @@ -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; + } +} |