From ca7eaeeed817001dc7cee4852a7e41f0982da1ef Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 16 Apr 2010 23:28:44 +0000 Subject: [PATCH] If a non-noreturn virtual member function is guaranteed not to return, do *not* suggest that the function could be attribute 'noreturn'; overridden functions may end up returning. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101572 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/AnalysisBasedWarnings.cpp | 21 ++++++++++++++++----- test/SemaCXX/warn-missing-noreturn.cpp | 5 +++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 8c42caf8bc..7c1d8cbae9 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -188,7 +188,7 @@ struct CheckFallThroughDiagnostics { unsigned diag_NeverFallThroughOrReturn; bool funMode; - static CheckFallThroughDiagnostics MakeForFunction() { + static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { CheckFallThroughDiagnostics D; D.diag_MaybeFallThrough_HasNoReturn = diag::warn_falloff_noreturn_function; @@ -198,8 +198,19 @@ struct CheckFallThroughDiagnostics { diag::warn_falloff_noreturn_function; D.diag_AlwaysFallThrough_ReturnsNonVoid = diag::warn_falloff_nonvoid_function; - D.diag_NeverFallThroughOrReturn = - diag::warn_suggest_noreturn_function; + + // Don't suggest that virtual functions be marked "noreturn", since they + // might be overridden by non-noreturn functions. + bool isVirtualMethod = false; + if (const CXXMethodDecl *Method = dyn_cast(Func)) + isVirtualMethod = Method->isVirtual(); + + if (!isVirtualMethod) + D.diag_NeverFallThroughOrReturn = + diag::warn_suggest_noreturn_function; + else + D.diag_NeverFallThroughOrReturn = 0; + D.funMode = true; return D; } @@ -295,7 +306,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, CD.diag_AlwaysFallThrough_ReturnsNonVoid); break; case NeverFallThroughOrReturn: - if (ReturnsVoid && !HasNoReturn) + if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) S.Diag(Compound->getLBracLoc(), CD.diag_NeverFallThroughOrReturn); break; @@ -360,7 +371,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (P.enableCheckFallThrough) { const CheckFallThroughDiagnostics &CD = (isa(D) ? CheckFallThroughDiagnostics::MakeForBlock() - : CheckFallThroughDiagnostics::MakeForFunction()); + : CheckFallThroughDiagnostics::MakeForFunction(D)); CheckFallThroughForBody(S, D, Body, BlockTy, CD, AC); } diff --git a/test/SemaCXX/warn-missing-noreturn.cpp b/test/SemaCXX/warn-missing-noreturn.cpp index 32d020f15f..5ca2eca61a 100644 --- a/test/SemaCXX/warn-missing-noreturn.cpp +++ b/test/SemaCXX/warn-missing-noreturn.cpp @@ -22,3 +22,8 @@ struct B { }; template void B::g(int); // expected-note {{in instantiation of function template specialization 'B::g' requested here}} + +// We don't want a warning here. +struct X { + virtual void g() { f(); } +}; -- 2.50.1