Index: clang-tools-extra/clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/misc/CMakeLists.txt +++ clang-tools-extra/clang-tidy/misc/CMakeLists.txt @@ -22,6 +22,7 @@ ConfusableIdentifierCheck.cpp HeaderIncludeCycleCheck.cpp IncludeCleanerCheck.cpp + IncompleteSwitchCheck.cpp MiscTidyModule.cpp MisleadingBidirectional.cpp MisleadingIdentifier.cpp Index: clang-tools-extra/clang-tidy/misc/IncompleteSwitchCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/misc/IncompleteSwitchCheck.h @@ -0,0 +1,29 @@ +//===--- IncompleteSwitchCheck.h - clang-tidy --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INCOMPLETESWITCHCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INCOMPLETESWITCHCHECK_H + +#include "../ClangTidyCheck.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +namespace clang::tidy::misc { + +class IncompleteSwitchCheck : public ClangTidyCheck { +public: + IncompleteSwitchCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace clang::tidy::misc + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INCOMPLETESWITCHCHECK_H Index: clang-tools-extra/clang-tidy/misc/IncompleteSwitchCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/misc/IncompleteSwitchCheck.cpp @@ -0,0 +1,36 @@ +//===--- IncompleteSwitchCheck.cpp - clang-tidy ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IncompleteSwitchCheck.h" +#include "clang/AST/ASTContext.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::misc { + +void IncompleteSwitchCheck::registerMatchers( + ast_matchers::MatchFinder *Finder) { + Finder->addMatcher( + switchStmt(has(implicitCastExpr().bind("cast")), + unless(hasAncestor(switchStmt(has(defaultStmt()))))) + .bind("switch"), + this); +} + +void IncompleteSwitchCheck::check( + const ast_matchers::MatchFinder::MatchResult &Result) { + const auto *c = Result.Nodes.getNodeAs("cast"); + if (c->getCastKind() == CK_IntegralCast) + return; + + const auto *s = Result.Nodes.getNodeAs("switch"); + diag(s->getSwitchLoc(), "switching on non-enum value without " + "default case may not cover all cases"); +} + +} // namespace clang::tidy::misc Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp +++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp @@ -14,6 +14,7 @@ #include "DefinitionsInHeadersCheck.h" #include "HeaderIncludeCycleCheck.h" #include "IncludeCleanerCheck.h" +#include "IncompleteSwitchCheck.h" #include "MisleadingBidirectional.h" #include "MisleadingIdentifier.h" #include "MisplacedConstCheck.h" @@ -46,6 +47,8 @@ CheckFactories.registerCheck( "misc-header-include-cycle"); CheckFactories.registerCheck("misc-include-cleaner"); + CheckFactories.registerCheck( + "misc-incomplete-switch"); CheckFactories.registerCheck( "misc-misleading-bidirectional"); CheckFactories.registerCheck( Index: clang-tools-extra/test/clang-tidy/checkers/misc/incomplete-switch.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/misc/incomplete-switch.cpp @@ -0,0 +1,27 @@ +// RUN: clang-tidy --checks='-*,misc-incomplete-switch' %s -- | FileCheck -implicit-check-not="{{warning|error}}:" %s + +void Positive() { + int i = 0; + // CHECK: [[@LINE+1]]:11: warning: switching on non-enum value without default case may not cover all cases [misc-incomplete-switch] + switch (i) { + case 0: + break; + } +} + +void Negative() { + enum E { eE1 }; + E e = eE1; + switch (e) { // no-warning + case eE1: + break; + } + + int i = 0; + switch (i) { // no-warning + case 0: + break; + default: + break; + } +}