diff options
| author | Mads Ravn <madsravn@gmail.com> | 2016-12-30 10:09:46 +0000 |
|---|---|---|
| committer | Mads Ravn <madsravn@gmail.com> | 2016-12-30 10:09:46 +0000 |
| commit | 72bcc049f2b2ed75fd74178b8b303768fdc85082 (patch) | |
| tree | 514b29fce4e59977cc03ba36d3485b72c1333890 /clang-tools-extra/clang-tidy/misc/StringCompareCheck.cpp | |
| parent | abf424334df700f84899c65658e5388c5e79c136 (diff) | |
| download | bcm5719-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.cpp | 82 |
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 |

