clang-tools  3.8.0
SimplifyBooleanExprCheck.h
Go to the documentation of this file.
1 //===--- SimplifyBooleanExpr.h clang-tidy -----------------------*- C++ -*-===//
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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
11 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
12 
13 #include "../ClangTidy.h"
14 
15 namespace clang {
16 namespace tidy {
17 namespace readability {
18 
19 /// Looks for boolean expressions involving boolean constants and simplifies
20 /// them to use the appropriate boolean expression directly.
21 ///
22 /// Examples:
23 ///
24 /// =========================================== ================
25 /// Initial expression Result
26 /// ------------------------------------------- ----------------
27 /// `if (b == true)` `if (b)`
28 /// `if (b == false)` `if (!b)`
29 /// `if (b && true)` `if (b)`
30 /// `if (b && false)` `if (false)`
31 /// `if (b || true)` `if (true)`
32 /// `if (b || false)` `if (b)`
33 /// `e ? true : false` `e`
34 /// `e ? false : true` `!e`
35 /// `if (true) t(); else f();` `t();`
36 /// `if (false) t(); else f();` `f();`
37 /// `if (e) return true; else return false;` `return e;`
38 /// `if (e) return false; else return true;` `return !e;`
39 /// `if (e) b = true; else b = false;` `b = e;`
40 /// `if (e) b = false; else b = true;` `b = !e;`
41 /// `if (e) return true; return false;` `return e;`
42 /// `if (e) return false; return true;` `return !e;`
43 /// =========================================== ================
44 ///
45 /// The resulting expression `e` is modified as follows:
46 /// 1. Unnecessary parentheses around the expression are removed.
47 /// 2. Negated applications of `!` are eliminated.
48 /// 3. Negated applications of comparison operators are changed to use the
49 /// opposite condition.
50 /// 4. Implicit conversions of pointer to `bool` are replaced with explicit
51 /// comparisons to `nullptr`.
52 /// 5. Implicit casts to `bool` are replaced with explicit casts to `bool`.
53 /// 6. Object expressions with `explicit operator bool` conversion operators
54 /// are replaced with explicit casts to `bool`.
55 ///
56 /// Examples:
57 /// 1. The ternary assignment `bool b = (i < 0) ? true : false;` has redundant
58 /// parentheses and becomes `bool b = i < 0;`.
59 ///
60 /// 2. The conditional return `if (!b) return false; return true;` has an
61 /// implied double negation and becomes `return b;`.
62 ///
63 /// 3. The conditional return `if (i < 0) return false; return true;` becomes
64 /// `return i >= 0;`.
65 ///
66 /// The conditional return `if (i != 0) return false; return true;` becomes
67 /// `return i == 0;`.
68 ///
69 /// 4. The conditional return `if (p) return true; return false;` has an
70 /// implicit conversion of a pointer to `bool` and becomes
71 /// `return p != nullptr;`.
72 ///
73 /// The ternary assignment `bool b = (i & 1) ? true : false;` has an
74 /// implicit conversion of `i & 1` to `bool` and becomes
75 /// `bool b = static_cast<bool>(i & 1);`.
76 ///
77 /// 5. The conditional return `if (i & 1) return true; else return false;` has
78 /// an implicit conversion of an integer quantity `i & 1` to `bool` and
79 /// becomes `return static_cast<bool>(i & 1);`
80 ///
81 /// 6. Given `struct X { explicit operator bool(); };`, and an instance `x` of
82 /// `struct X`, the conditional return `if (x) return true; return false;`
83 /// becomes `return static_cast<bool>(x);`
84 ///
85 /// When a conditional boolean return or assignment appears at the end of a
86 /// chain of `if`, `else if` statements, the conditional statement is left
87 /// unchanged unless the option `ChainedConditionalReturn` or
88 /// `ChainedConditionalAssignment`, respectively, is specified as non-zero.
89 /// The default value for both options is zero.
90 ///
92 public:
94 
96  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
97  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
98 
99 private:
100  void matchBoolBinOpExpr(ast_matchers::MatchFinder *Finder, bool Value,
101  StringRef OperatorName, StringRef BooleanId);
102 
103  void matchExprBinOpBool(ast_matchers::MatchFinder *Finder, bool Value,
104  StringRef OperatorName, StringRef BooleanId);
105 
106  void matchBoolCompOpExpr(ast_matchers::MatchFinder *Finder, bool Value,
107  StringRef OperatorName, StringRef BooleanId);
108 
109  void matchExprCompOpBool(ast_matchers::MatchFinder *Finder, bool Value,
110  StringRef OperatorName, StringRef BooleanId);
111 
112  void matchBoolCondition(ast_matchers::MatchFinder *Finder, bool Value,
113  StringRef BooleanId);
114 
115  void matchTernaryResult(ast_matchers::MatchFinder *Finder, bool Value,
116  StringRef TernaryId);
117 
118  void matchIfReturnsBool(ast_matchers::MatchFinder *Finder, bool Value,
119  StringRef Id);
120 
121  void matchIfAssignsBool(ast_matchers::MatchFinder *Finder, bool Value,
122  StringRef Id);
123 
124  void matchCompoundIfReturnsBool(ast_matchers::MatchFinder *Finder, bool Value,
125  StringRef Id);
126 
127  void
128  replaceWithExpression(const ast_matchers::MatchFinder::MatchResult &Result,
129  const CXXBoolLiteralExpr *BoolLiteral, bool UseLHS,
130  bool Negated = false);
131 
132  void
133  replaceWithThenStatement(const ast_matchers::MatchFinder::MatchResult &Result,
134  const CXXBoolLiteralExpr *BoolLiteral);
135 
136  void
137  replaceWithElseStatement(const ast_matchers::MatchFinder::MatchResult &Result,
138  const CXXBoolLiteralExpr *FalseConditionRemoved);
139 
140  void
141  replaceWithCondition(const ast_matchers::MatchFinder::MatchResult &Result,
142  const ConditionalOperator *Ternary,
143  bool Negated = false);
144 
145  void replaceWithReturnCondition(
146  const ast_matchers::MatchFinder::MatchResult &Result, const IfStmt *If,
147  bool Negated = false);
148 
149  void
150  replaceWithAssignment(const ast_matchers::MatchFinder::MatchResult &Result,
151  const IfStmt *If, bool Negated = false);
152 
153  void replaceCompoundReturnWithCondition(
154  const ast_matchers::MatchFinder::MatchResult &Result,
155  const CompoundStmt *Compound, bool Negated = false);
156 
157  void issueDiag(const ast_matchers::MatchFinder::MatchResult &Result,
158  SourceLocation Loc, StringRef Description,
159  SourceRange ReplacementRange, StringRef Replacement);
160 
161  const bool ChainedConditionalReturn;
162  const bool ChainedConditionalAssignment;
163 };
164 
165 } // namespace readability
166 } // namespace tidy
167 } // namespace clang
168 
169 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
SourceLocation Loc
'#' location in the include directive
StringHandle Name
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:188
void storeOptions(ClangTidyOptions::OptionMap &Options) override
Should store all options supported by this check with their current values or default values for opti...
Looks for boolean expressions involving boolean constants and simplifies them to use the appropriate ...
Base class for all clang-tidy checks.
Definition: ClangTidy.h:102
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
SimplifyBooleanExprCheck(StringRef Name, ClangTidyContext *Context)
std::map< std::string, std::string > OptionMap
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register ASTMatchers with Finder.
ClangTidyContext & Context
Definition: ClangTidy.cpp:93
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
const NamedDecl * Result
Definition: USRFinder.cpp:121