]> granicus.if.org Git - clang/commitdiff
Suppress warning on unreachable [[clang::fallthrough]] within a template instantiation.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 22 Mar 2017 01:49:19 +0000 (01:49 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Wed, 22 Mar 2017 01:49:19 +0000 (01:49 +0000)
We don't know whether some other instantiation of the template might be able to
reach the annotation, so warning on it has a high chance of false positives.

Patch by Ahmed Asadi!

Differential Revision: https://reviews.llvm.org/D31069

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@298477 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/AnalysisBasedWarnings.cpp
test/SemaCXX/P30636.cpp [new file with mode: 0644]

index a987a8ce0b31079c607159e781d0e1ba3ae5749b..50ad113fc8802f2094d9d98861cbcea03242c965 100644 (file)
@@ -972,7 +972,8 @@ namespace {
       }
     }
 
-    bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) {
+    bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
+                                   bool IsTemplateInstantiation) {
       assert(!ReachableBlocks.empty() && "ReachableBlocks empty");
 
       int UnannotatedCnt = 0;
@@ -1002,8 +1003,12 @@ namespace {
                ElemIt != ElemEnd; ++ElemIt) {
             if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) {
               if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) {
-                S.Diag(AS->getLocStart(),
-                       diag::warn_fallthrough_attr_unreachable);
+                // Don't issue a warning for an unreachable fallthrough
+                // attribute in template instantiations as it may not be
+                // unreachable in all instantiations of the template.
+                if (!IsTemplateInstantiation)
+                  S.Diag(AS->getLocStart(),
+                         diag::warn_fallthrough_attr_unreachable);
                 markFallthroughVisited(AS);
                 ++AnnotatedCnt;
                 break;
@@ -1164,7 +1169,11 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC,
 
     int AnnotatedCnt;
 
-    if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt))
+    bool IsTemplateInstantiation = false;
+    if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(AC.getDecl()))
+      IsTemplateInstantiation = Function->isTemplateInstantiation();
+    if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt,
+                                      IsTemplateInstantiation))
       continue;
 
     S.Diag(Label->getLocStart(),
diff --git a/test/SemaCXX/P30636.cpp b/test/SemaCXX/P30636.cpp
new file mode 100644 (file)
index 0000000..2e2affb
--- /dev/null
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wimplicit-fallthrough %s
+// expected-no-diagnostics
+
+template<bool param>
+int fallthrough_template(int i)
+{
+  switch (i) {
+    case 1:
+      if (param)
+        return 3;
+      [[clang::fallthrough]]; // no warning here, for an unreachable annotation (in the fallthrough_template<true> case) in a template function
+    case 2:
+      return 4;
+    default:
+      return 5;
+  }
+}
+                                      
+template int fallthrough_template<true>(int);
+