summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp
diff options
context:
space:
mode:
authorMads Ravn <madsravn@gmail.com>2016-12-30 10:09:46 +0000
committerMads Ravn <madsravn@gmail.com>2016-12-30 10:09:46 +0000
commit72bcc049f2b2ed75fd74178b8b303768fdc85082 (patch)
tree514b29fce4e59977cc03ba36d3485b72c1333890 /clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp
parentabf424334df700f84899c65658e5388c5e79c136 (diff)
downloadbcm5719-llvm-72bcc049f2b2ed75fd74178b8b303768fdc85082.tar.gz
bcm5719-llvm-72bcc049f2b2ed75fd74178b8b303768fdc85082.zip
[clang-tidy] Add check 'misc-string-compare'.
I have a created a new check for clang tidy: misc-string-compare. This will check for incorrect usage of std::string::compare when used to check equality or inequality of string instead of the string equality or inequality operators. Example: ``` std::string str1, str2; if (str1.compare(str2)) { } ``` Reviewers: hokein, aaron.ballman, alexfh, malcolm.parsons Subscribers: xazax.hun, Eugene.Zelenko, cfe-commits, malcolm.parsons, Prazek, mgorny, JDevlieghere Differential Revision: https://reviews.llvm.org/D27210 llvm-svn: 290747
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp b/clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp
new file mode 100644
index 00000000000..b6a42953335
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp
@@ -0,0 +1,82 @@
+//===--- MiscStringCompare.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 "StringCompareCheck.h"
+#include "../utils/FixItHintUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+static const StringRef CompareMessage = "do not use 'compare' to test equality "
+ "of strings; use the string equality "
+ "operator instead";
+
+void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ const auto StrCompare = cxxMemberCallExpr(
+ callee(cxxMethodDecl(hasName("compare"),
+ ofClass(classTemplateSpecializationDecl(
+ hasName("::std::basic_string"))))),
+ hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+ callee(memberExpr().bind("str1")));
+
+ // First and second case: cast str.compare(str) to boolean.
+ Finder->addMatcher(implicitCastExpr(hasImplicitDestinationType(booleanType()),
+ has(StrCompare))
+ .bind("match1"),
+ this);
+
+ // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
+ Finder->addMatcher(
+ binaryOperator(anyOf(hasOperatorName("=="), hasOperatorName("!=")),
+ hasEitherOperand(StrCompare.bind("compare")),
+ hasEitherOperand(integerLiteral(equals(0)).bind("zero")))
+ .bind("match2"),
+ this);
+}
+
+void StringCompareCheck::check(const MatchFinder::MatchResult &Result) {
+ if (const auto *Matched = Result.Nodes.getNodeAs<Stmt>("match1")) {
+ diag(Matched->getLocStart(), CompareMessage);
+ return;
+ }
+
+ if (const auto *Matched = Result.Nodes.getNodeAs<Stmt>("match2")) {
+ const ASTContext &Ctx = *Result.Context;
+
+ if (const auto *Zero = Result.Nodes.getNodeAs<Stmt>("zero")) {
+ const auto *Str1 = Result.Nodes.getNodeAs<MemberExpr>("str1");
+ const auto *Str2 = Result.Nodes.getNodeAs<Stmt>("str2");
+ const auto *Compare = Result.Nodes.getNodeAs<Stmt>("compare");
+
+ auto Diag = diag(Matched->getLocStart(), CompareMessage);
+
+ if (Str1->isArrow())
+ Diag << FixItHint::CreateInsertion(Str1->getLocStart(), "*");
+
+ Diag << tooling::fixit::createReplacement(*Zero, *Str2, Ctx)
+ << tooling::fixit::createReplacement(*Compare, *Str1->getBase(),
+ Ctx);
+ }
+ }
+
+ // FIXME: Add fixit to fix the code for case one and two (match1).
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
OpenPOWER on IntegriCloud