[PATCH] [clang-tidy] Add check for possibly incomplete switch statements
Benjamin Bannier
bbannier at gmail.com
Sun Aug 3 07:55:27 PDT 2014
While clang issues a warns about a possibly incomplete switch statement
when switching over an enum variable and failing to cover all enum
values (either explicitly or with a default case), no such warning is
emitted if a plain integer variable is used as switch variable.
Add a clang-tidy check to diagnose these scenarios.
No fixit hint is provided since there are multiple possible solutions.
---
clang-tidy/misc/CMakeLists.txt | 1 +
clang-tidy/misc/IncompleteSwitchCheck.cpp | 27 +++++++++++++++++++++++++++
clang-tidy/misc/IncompleteSwitchCheck.h | 17 +++++++++++++++++
clang-tidy/misc/MiscTidyModule.cpp | 4 ++++
test/clang-tidy/incomplete-switch.cpp | 27 +++++++++++++++++++++++++++
5 files changed, 76 insertions(+)
create mode 100644 clang-tidy/misc/IncompleteSwitchCheck.cpp
create mode 100644 clang-tidy/misc/IncompleteSwitchCheck.h
create mode 100644 test/clang-tidy/incomplete-switch.cpp
diff --git a/clang-tidy/misc/CMakeLists.txt b/clang-tidy/misc/CMakeLists.txt
index fbe5bb0..b2aa06a 100644
--- a/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tidy/misc/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyMiscModule
ArgumentCommentCheck.cpp
BoolPointerImplicitConversion.cpp
+ IncompleteSwitch.cpp
MiscTidyModule.cpp
RedundantSmartptrGet.cpp
SwappedArgumentsCheck.cpp
diff --git a/clang-tidy/misc/IncompleteSwitchCheck.cpp b/clang-tidy/misc/IncompleteSwitchCheck.cpp
new file mode 100644
index 0000000..f36414c
--- /dev/null
+++ b/clang-tidy/misc/IncompleteSwitchCheck.cpp
@@ -0,0 +1,27 @@
+#include "IncompleteSwitchCheck.h"
+#include <iostream>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+void
+IncompleteSwitchCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
+ Finder->addMatcher(
+ switchStmt(hasDescendant(implicitCastExpr().bind("cast")),
+ unless(hasDescendant(defaultStmt()))).bind("switch"),
+ this);
+}
+
+void IncompleteSwitchCheck::check(
+ const ast_matchers::MatchFinder::MatchResult &Result) {
+ const auto c = Result.Nodes.getNodeAs<ImplicitCastExpr>("cast");
+ if (c->getCastKind() == CK_IntegralCast)
+ return;
+
+ const auto s = Result.Nodes.getNodeAs<SwitchStmt>("switch");
+ diag(s->getCond()->getLocStart(), "switching on non-enum value without "
+ "default case may not cover all cases");
+}
+} // tidy
+} // clang
diff --git a/clang-tidy/misc/IncompleteSwitchCheck.h b/clang-tidy/misc/IncompleteSwitchCheck.h
new file mode 100644
index 0000000..697f028
--- /dev/null
+++ b/clang-tidy/misc/IncompleteSwitchCheck.h
@@ -0,0 +1,17 @@
+#ifndef SWITCHONNONENUMWITHOUTDEFAULTCHECK_H
+#define SWITCHONNONENUMWITHOUTDEFAULTCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+class IncompleteSwitchCheck : public ClangTidyCheck {
+public:
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+} // tidy
+} // clang
+
+#endif /* end of include guard: SWITCHONNONENUMWITHOUTDEFAULTCHECK_H */
diff --git a/clang-tidy/misc/MiscTidyModule.cpp b/clang-tidy/misc/MiscTidyModule.cpp
index 8cf70d3..7fb7c0b 100644
--- a/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tidy/misc/MiscTidyModule.cpp
@@ -12,6 +12,7 @@
#include "../ClangTidyModuleRegistry.h"
#include "ArgumentCommentCheck.h"
#include "BoolPointerImplicitConversion.h"
+#include "IncompleteSwitchCheck.h"
#include "RedundantSmartptrGet.h"
#include "SwappedArgumentsCheck.h"
#include "UndelegatedConstructor.h"
@@ -34,6 +35,9 @@ public:
"misc-redundant-smartptr-get",
new ClangTidyCheckFactory<RedundantSmartptrGet>());
CheckFactories.addCheckFactory(
+ "misc-incomplete-switch",
+ new ClangTidyCheckFactory<IncompleteSwitchCheck>());
+ CheckFactories.addCheckFactory(
"misc-swapped-arguments",
new ClangTidyCheckFactory<SwappedArgumentsCheck>());
CheckFactories.addCheckFactory(
diff --git a/test/clang-tidy/incomplete-switch.cpp b/test/clang-tidy/incomplete-switch.cpp
new file mode 100644
index 0000000..5cc6a05
--- /dev/null
+++ b/test/clang-tidy/incomplete-switch.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-tidy --checks='-*,misc-incomplete-switch' %s -- | FileCheck %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;
+ }
+}
--
1.7.10.4
--
"Good judgment comes from experience. Experience comes from bad judgment."
More information about the cfe-commits
mailing list