aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp21
-rw-r--r--test/SemaCXX/warn-missing-noreturn.cpp5
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<CXXMethodDecl>(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<BlockDecl>(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>(int); // expected-note {{in instantiation of function template specialization 'B::g<int>' requested here}}
+
+// We don't want a warning here.
+struct X {
+ virtual void g() { f(); }
+};