UseBoolLiteralsCheck.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. //===--- UseBoolLiteralsCheck.cpp - clang-tidy-----------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "UseBoolLiteralsCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. #include "clang/Lex/Lexer.h"
  12. using namespace clang::ast_matchers;
  13. namespace clang::tidy::modernize {
  14. UseBoolLiteralsCheck::UseBoolLiteralsCheck(StringRef Name,
  15. ClangTidyContext *Context)
  16. : ClangTidyCheck(Name, Context),
  17. IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
  18. void UseBoolLiteralsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  19. Options.store(Opts, "IgnoreMacros", IgnoreMacros);
  20. }
  21. void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
  22. Finder->addMatcher(
  23. traverse(
  24. TK_AsIs,
  25. implicitCastExpr(
  26. has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
  27. hasImplicitDestinationType(qualType(booleanType())),
  28. unless(isInTemplateInstantiation()),
  29. anyOf(hasParent(explicitCastExpr().bind("cast")), anything()))),
  30. this);
  31. Finder->addMatcher(
  32. traverse(TK_AsIs,
  33. conditionalOperator(
  34. hasParent(implicitCastExpr(
  35. hasImplicitDestinationType(qualType(booleanType())),
  36. unless(isInTemplateInstantiation()))),
  37. eachOf(hasTrueExpression(ignoringParenImpCasts(
  38. integerLiteral().bind("literal"))),
  39. hasFalseExpression(ignoringParenImpCasts(
  40. integerLiteral().bind("literal")))))),
  41. this);
  42. }
  43. void UseBoolLiteralsCheck::check(const MatchFinder::MatchResult &Result) {
  44. const auto *Literal = Result.Nodes.getNodeAs<IntegerLiteral>("literal");
  45. const auto *Cast = Result.Nodes.getNodeAs<Expr>("cast");
  46. bool LiteralBooleanValue = Literal->getValue().getBoolValue();
  47. if (Literal->isInstantiationDependent())
  48. return;
  49. const Expr *Expression = Cast ? Cast : Literal;
  50. bool InMacro = Expression->getBeginLoc().isMacroID();
  51. if (InMacro && IgnoreMacros)
  52. return;
  53. auto Diag =
  54. diag(Expression->getExprLoc(),
  55. "converting integer literal to bool, use bool literal instead");
  56. if (!InMacro)
  57. Diag << FixItHint::CreateReplacement(
  58. Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false");
  59. }
  60. } // namespace clang::tidy::modernize