summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp
diff options
context:
space:
mode:
authorEtienne Bergeron <etienneb@google.com>2016-03-31 18:12:23 +0000
committerEtienne Bergeron <etienneb@google.com>2016-03-31 18:12:23 +0000
commit3e4adf17625595d9425fb8109126af22475f54c0 (patch)
tree6f56b1b5347bb7ffadff6b59fc0371e29ad42ed2 /clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp
parent4badd6aaf30859ce9b89960d8cae2b9ecd1dacca (diff)
downloadbcm5719-llvm-3e4adf17625595d9425fb8109126af22475f54c0.tar.gz
bcm5719-llvm-3e4adf17625595d9425fb8109126af22475f54c0.zip
[clang-tidy] Add a new checker to detect missing comma in initializer list.
Summary: This checker is able to detect missing comma in an array of string literals. ``` const char* A[] = { "abc", "def" // missing comma (no compiler warnings) "ghi", }; ``` The ratio of false-positive is reduced by restricting the size of the array considered and the ratio of missing comma. To validate the quantity of false positive, the checker was tried over LLVM and chromium code and detected these cases: [[ http://reviews.llvm.org/D18454 | http://reviews.llvm.org/D18454 ]] [[https://codereview.chromium.org/1807753002/ | https://codereview.chromium.org/1807753002/]] [[https://codereview.chromium.org/1826193002/ | https://codereview.chromium.org/1826193002/]] [[https://codereview.chromium.org/1805713002/ | https://codereview.chromium.org/1805713002/]] Reviewers: alexfh Subscribers: LegalizeAdulthood, szdominik, xazax.hun, cfe-commits Differential Revision: http://reviews.llvm.org/D18457 llvm-svn: 265033
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp b/clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp
new file mode 100644
index 00000000000..a3a479c89b3
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/SuspiciousMissingCommaCheck.cpp
@@ -0,0 +1,80 @@
+//===--- SuspiciousMissingCommaCheck.cpp - clang-tidy----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuspiciousMissingCommaCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+namespace {
+
+AST_MATCHER(StringLiteral, isConcatenatedLiteral) {
+ return Node.getNumConcatenated() > 1;
+}
+
+} // namespace
+
+SuspiciousMissingCommaCheck::SuspiciousMissingCommaCheck(
+ StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ SizeThreshold(Options.get("SizeThreshold", 5U)),
+ RatioThreshold(std::stod(Options.get("RatioThreshold", ".2"))) {}
+
+void SuspiciousMissingCommaCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "SizeThreshold", SizeThreshold);
+ Options.store(Opts, "RatioThreshold", std::to_string(RatioThreshold));
+}
+
+void SuspiciousMissingCommaCheck::registerMatchers(MatchFinder *Finder) {
+ const auto ConcatenatedStringLiteral =
+ stringLiteral(isConcatenatedLiteral()).bind("str");
+
+ const auto StringsInitializerList =
+ initListExpr(hasType(constantArrayType()),
+ has(expr(ignoringImpCasts(ConcatenatedStringLiteral))));
+
+ Finder->addMatcher(StringsInitializerList.bind("list"), this);
+}
+
+void SuspiciousMissingCommaCheck::check(
+ const MatchFinder::MatchResult &Result) {
+ const auto *InitializerList = Result.Nodes.getNodeAs<InitListExpr>("list");
+ const auto *ConcatenatedLiteral = Result.Nodes.getNodeAs<Expr>("str");
+ assert(InitializerList && ConcatenatedLiteral);
+
+ // Skip small arrays as they often generate false-positive.
+ unsigned int Size = InitializerList->getNumInits();
+ if (Size < SizeThreshold) return;
+
+ // Count the number of occurence of concatenated string literal.
+ unsigned int Count = 0;
+ for (unsigned int i = 0; i < Size; ++i) {
+ const Expr *Child = InitializerList->getInit(i)->IgnoreImpCasts();
+ if (const auto *Literal = dyn_cast<StringLiteral>(Child)) {
+ if (Literal->getNumConcatenated() > 1) ++Count;
+ }
+ }
+
+ // Warn only when concatenation is not common in this initializer list.
+ // The current threshold is set to less than 1/5 of the string literals.
+ if (double(Count) / Size > RatioThreshold) return;
+
+ diag(ConcatenatedLiteral->getLocStart(),
+ "suspicious string literal, probably missing a comma");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
OpenPOWER on IntegriCloud