]> granicus.if.org Git - clang/commitdiff
If a non-noreturn virtual member function is guaranteed not to return,
authorDouglas Gregor <dgregor@apple.com>
Fri, 16 Apr 2010 23:28:44 +0000 (23:28 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 16 Apr 2010 23:28:44 +0000 (23:28 +0000)
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
test/SemaCXX/warn-missing-noreturn.cpp

index 8c42caf8bcf194ae9517f70bdec298c1650d67c6..7c1d8cbae9ee9ea47dc2f92babcab5570e68a9e1 100644 (file)
@@ -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);
   }
 
index 32d020f15f3d2f4d1afb3400405d864ee95c283b..5ca2eca61a936f7151f6268917f40db3d1ceea20 100644 (file)
@@ -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(); }
+};