xref: /llvm-project/clang-tools-extra/clang-tidy/modernize/UseBoolLiteralsCheck.cpp (revision 31176afd16dcefc09cadc737f5b4fd43a3c50a80)
1 //===--- UseBoolLiteralsCheck.cpp - clang-tidy-----------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "UseBoolLiteralsCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace modernize {
20 
21 UseBoolLiteralsCheck::UseBoolLiteralsCheck(StringRef Name,
22                                            ClangTidyContext *Context)
23     : ClangTidyCheck(Name, Context),
24       IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {}
25 
26 void UseBoolLiteralsCheck::registerMatchers(MatchFinder *Finder) {
27   if (!getLangOpts().CPlusPlus)
28     return;
29 
30   Finder->addMatcher(
31       implicitCastExpr(
32           has(ignoringParenImpCasts(integerLiteral().bind("literal"))),
33           hasImplicitDestinationType(qualType(booleanType())),
34           unless(isInTemplateInstantiation()),
35           anyOf(hasParent(explicitCastExpr().bind("cast")), anything())),
36       this);
37 
38   Finder->addMatcher(
39       conditionalOperator(
40           hasParent(implicitCastExpr(
41               hasImplicitDestinationType(qualType(booleanType())),
42               unless(isInTemplateInstantiation()))),
43           eachOf(hasTrueExpression(
44                      ignoringParenImpCasts(integerLiteral().bind("literal"))),
45                  hasFalseExpression(
46                      ignoringParenImpCasts(integerLiteral().bind("literal"))))),
47       this);
48 }
49 
50 void UseBoolLiteralsCheck::check(const MatchFinder::MatchResult &Result) {
51   const auto *Literal = Result.Nodes.getNodeAs<IntegerLiteral>("literal");
52   const auto *Cast = Result.Nodes.getNodeAs<Expr>("cast");
53   bool LiteralBooleanValue = Literal->getValue().getBoolValue();
54 
55   if (Literal->isInstantiationDependent())
56     return;
57 
58   const Expr *Expression = Cast ? Cast : Literal;
59 
60   bool InMacro = Expression->getLocStart().isMacroID();
61 
62   if (InMacro && IgnoreMacros)
63     return;
64 
65   auto Diag =
66       diag(Expression->getExprLoc(),
67            "converting integer literal to bool, use bool literal instead");
68 
69   if (!InMacro)
70     Diag << FixItHint::CreateReplacement(
71         Expression->getSourceRange(), LiteralBooleanValue ? "true" : "false");
72 }
73 
74 } // namespace modernize
75 } // namespace tidy
76 } // namespace clang
77