alexey.knyshev updated this revision to Diff 126293.
alexey.knyshev added a comment.
1. Now implemented via MatchFinder
2. Added missing License header
3. Pass all StringRefs by value
4. Method names now start from small letter
5. Using StringRef::edit_distance instead of custom "similarity" metric
6. Various other formating fixes
Repository:
rC Clang
https://reviews.llvm.org/D40715
Files:
include/clang/StaticAnalyzer/Checkers/Checkers.td
lib/StaticAnalyzer/Checkers/CMakeLists.txt
lib/StaticAnalyzer/Checkers/LabelInsideSwitchChecker.cpp
test/Analysis/label-inside-switch.c
Index: test/Analysis/label-inside-switch.c
===================================================================
--- test/Analysis/label-inside-switch.c
+++ test/Analysis/label-inside-switch.c
@@ -0,0 +1,67 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core.LabelInsideSwitch -w -verify %s
+
+int caseAndDefaultMissprint(unsigned count) {
+ int res = 0;
+ switch (count) {
+ case 1:
+ res = 1;
+ break;
+ cas: // expected-warning {{label inside switch (did you mean 'case'?)}}
+ case 2:
+ res = 5;
+ break;
+ case 3:
+ exit(1);
+ defaul: // expected-warning {{label inside switch (did you mean 'default'?)}}
+ return -1;
+ }
+
+ return res;
+}
+
+int nestedSwitch(unsigned x, unsigned y) {
+ int res = 0;
+ switch (x) {
+ case 1:
+ res = 1;
+ break;
+ case 2:
+ res = 5;
+ break;
+ case 3:
+ switch (y) {
+ case 1:
+ case 2:
+ case 4:
+ res = x * y;
+ break;
+ defaul:; // expected-warning {{label inside switch (did you mean 'default'?)}}
+ }
+ break;
+ default:;
+ }
+
+ return res;
+}
+
+int arbitaryLabelInSwitch(int arg) {
+ switch (arg) {
+ case 1:
+ case 2:
+ label: // expected-warning {{label inside switch}}
+ case 3:
+ break;
+ }
+
+ return 0;
+}
+
+int unreachableLabelInSwitch(int arg) {
+ switch (arg) {
+ unreachable: // expected-warning {{label inside switch}}
+ case 1:
+ return 0;
+ default:
+ return arg;
+ }
+}
Index: lib/StaticAnalyzer/Checkers/LabelInsideSwitchChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/LabelInsideSwitchChecker.cpp
+++ lib/StaticAnalyzer/Checkers/LabelInsideSwitchChecker.cpp
@@ -0,0 +1,104 @@
+//== LabelInsideSwitchChecker.cpp - Lable inside switch checker -*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This defines LabelInsideSwitchChecker, which looks for typos in switch
+// cases like missprinting 'defualt', 'cas' or other accidental insertion
+// of labeled statement.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+class LabelInsideSwitchChecker : public Checker<check::ASTCodeBody> {
+public:
+ void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
+ BugReporter &BR) const;
+};
+
+static StringRef suggestTypoFix(StringRef Str) {
+ StringRef DefaultStr("default");
+ const unsigned DefaultStrED =
+ Str.edit_distance(DefaultStr, true, DefaultStr.size() / 2);
+
+ if (DefaultStrED <= DefaultStr.size() / 2)
+ return DefaultStr;
+
+ StringRef CaseStr("case");
+ const unsigned CaseStrED =
+ Str.edit_distance(CaseStr, true, CaseStr.size() / 2);
+
+ if (CaseStrED <= CaseStr.size() / 2)
+ return CaseStr;
+
+ return StringRef();
+}
+
+class Callback : public MatchFinder::MatchCallback {
+ const CheckerBase *C;
+ BugReporter &BR;
+ AnalysisDeclContext *AC;
+
+ void report(const LabelStmt *L) {
+ StringRef Suggest = suggestTypoFix(L->getName());
+
+ SmallString<64> Message;
+ llvm::raw_svector_ostream OS(Message);
+ OS << "label inside switch";
+ if (!Suggest.empty())
+ OS << " (did you mean '" << Suggest << "'?)";
+
+ PathDiagnosticLocation Loc =
+ PathDiagnosticLocation::createBegin(L, BR.getSourceManager(), AC);
+ BR.EmitBasicReport(AC->getDecl(), C, "Labeled statement inside switch",
+ categories::LogicError, Message, Loc,
+ L->getSourceRange());
+ }
+
+public:
+ Callback(const CheckerBase *C, BugReporter &BR, AnalysisDeclContext *AC)
+ : C(C), BR(BR), AC(AC) {}
+
+ virtual void run(const MatchFinder::MatchResult &Result) override {
+ if (const LabelStmt *L = Result.Nodes.getNodeAs<LabelStmt>("label"))
+ report(L);
+ if (const LabelStmt *L = Result.Nodes.getNodeAs<LabelStmt>("label_in_case"))
+ report(L);
+ }
+};
+} // end anonymous namespace
+
+void LabelInsideSwitchChecker::checkASTCodeBody(const Decl *D,
+ AnalysisManager &Mgr,
+ BugReporter &BR) const {
+ auto LabelStmt = stmt(hasDescendant(switchStmt(
+ eachOf(has(compoundStmt(forEach(labelStmt().bind("label")))),
+ forEachSwitchCase(forEach(labelStmt().bind("label_in_case")))))));
+
+ MatchFinder F;
+ Callback CB(this, BR, Mgr.getAnalysisDeclContext(D));
+
+ F.addMatcher(LabelStmt, &CB);
+ F.match(*D->getBody(), Mgr.getASTContext());
+}
+
+namespace clang {
+namespace ento {
+void registerLabelInsideSwitchChecker(CheckerManager &Mgr) {
+ Mgr.registerChecker<LabelInsideSwitchChecker>();
+}
+} // namespace ento
+} // namespace clang
Index: lib/StaticAnalyzer/Checkers/CMakeLists.txt
===================================================================
--- lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -43,6 +43,7 @@
IteratorChecker.cpp
IvarInvalidationChecker.cpp
LLVMConventionsChecker.cpp
+ LabelInsideSwitchChecker.cpp
LocalizationChecker.cpp
MacOSKeychainAPIChecker.cpp
MacOSXAPIChecker.cpp
Index: include/clang/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -160,6 +160,10 @@
HelpText<"Warn about unintended use of identical expressions in operators">,
DescFile<"IdenticalExprChecker.cpp">;
+def LabelInsideSwitchChecker : Checker<"LabelInsideSwitch">,
+ HelpText<"Warn about labeled statements inside switch">,
+ DescFile<"LabelInsideSwitchChecker.cpp">;
+
def FixedAddressChecker : Checker<"FixedAddr">,
HelpText<"Check for assignment of a fixed address to a pointer">,
DescFile<"FixedAddressChecker.cpp">;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits