Index: clang/include/clang/Analysis/Analyses/ReachableCode.h =================================================================== --- clang/include/clang/Analysis/Analyses/ReachableCode.h +++ clang/include/clang/Analysis/Analyses/ReachableCode.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H #define LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" //===----------------------------------------------------------------------===// @@ -61,8 +62,7 @@ llvm::BitVector &Reachable); void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, - Callback &CB); - + const DiagnosticsEngine &Diag, Callback &CB); }} // end namespace clang::reachable_code #endif Index: clang/lib/Analysis/ReachableCode.cpp =================================================================== --- clang/lib/Analysis/ReachableCode.cpp +++ clang/lib/Analysis/ReachableCode.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/AST/Attr.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" @@ -22,6 +23,7 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" #include @@ -408,15 +410,15 @@ PP(PP), C(C) {} void enqueue(const CFGBlock *block); - unsigned scanBackwards(const CFGBlock *Start, - clang::reachable_code::Callback &CB); + unsigned scanBackwards(const CFGBlock *Start, const DiagnosticsEngine &Diag, + clang::reachable_code::Callback &CB); bool isDeadCodeRoot(const CFGBlock *Block); const Stmt *findDeadCode(const CFGBlock *Block); - void reportDeadCode(const CFGBlock *B, - const Stmt *S, + void reportDeadCode(const CFGBlock *B, const Stmt *S, + const DiagnosticsEngine &Diag, clang::reachable_code::Callback &CB); }; } @@ -488,6 +490,7 @@ } unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start, + const DiagnosticsEngine &Diag, clang::reachable_code::Callback &CB) { unsigned count = 0; @@ -521,7 +524,7 @@ } if (isDeadCodeRoot(Block)) { - reportDeadCode(Block, S, CB); + reportDeadCode(Block, S, Diag, CB); count += scanMaybeReachableFromBlock(Block, PP, Reachable); } else { @@ -540,7 +543,7 @@ const CFGBlock *Block = I.first; if (Reachable[Block->getBlockID()]) continue; - reportDeadCode(Block, I.second, CB); + reportDeadCode(Block, I.second, Diag, CB); count += scanMaybeReachableFromBlock(Block, PP, Reachable); } } @@ -613,8 +616,8 @@ return S->getBeginLoc(); } -void DeadCodeScan::reportDeadCode(const CFGBlock *B, - const Stmt *S, +void DeadCodeScan::reportDeadCode(const CFGBlock *B, const Stmt *S, + const DiagnosticsEngine &Diag, clang::reachable_code::Callback &CB) { // Classify the unreachable code found, or suppress it in some cases. reachable_code::UnreachableKind UK = reachable_code::UK_Other; @@ -663,6 +666,16 @@ } } + // If S is `[[fallthrough]];` and `-Wunreachable-code-fallthrough` is enabled, + // suppress `code will never be executed` warning to avoid generating + // diagnostic twice + const AttributedStmt *AS = dyn_cast(S); + if (AS && hasSpecificAttr(AS->getAttrs()) && + !Diag.isIgnored(diag::warn_unreachable_fallthrough_attr, + SourceLocation())) { + return; + } + SourceRange R1, R2; SourceLocation Loc = GetUnreachableLoc(S, R1, R2); CB.HandleUnreachable(UK, Loc, SilenceableCondVal, R1, R2); @@ -682,7 +695,7 @@ } void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, - Callback &CB) { + const DiagnosticsEngine &Diag, Callback &CB) { CFG *cfg = AC.getCFG(); if (!cfg) @@ -713,11 +726,10 @@ continue; DeadCodeScan DS(reachable, PP, AC.getASTContext()); - numReachable += DS.scanBackwards(block, CB); + numReachable += DS.scanBackwards(block, Diag, CB); if (numReachable == cfg->getNumBlockIDs()) return; } } - }} // end namespace clang::reachable_code Index: clang/lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- clang/lib/Sema/AnalysisBasedWarnings.cpp +++ clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -123,7 +123,8 @@ return; UnreachableCodeHandler UC(S); - reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), UC); + reachable_code::FindUnreachableCode(AC, S.getPreprocessor(), + S.getDiagnostics(), UC); } namespace { Index: clang/test/Sema/warn-unreachable-fallthrough.c =================================================================== --- /dev/null +++ clang/test/Sema/warn-unreachable-fallthrough.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c2x -Wunreachable-code-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c2x -Wunreachable-code %s +// RUN: %clang_cc1 -fsyntax-only -verify=code -std=c2x -Wunreachable-code -Wno-unreachable-code-fallthrough %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c2x -Wno-unreachable-code -Wunreachable-code-fallthrough %s + +int n; +void f(void){ + switch (n){ + [[fallthrough]]; // expected-warning{{fallthrough annotation in unreachable code}} + // code-warning@-1{{never be executed}} + case 1:; + } +}