Fuss around with some types to get closer to clang style.
Simplify replacement of matching expressions by eliminating duplication.
http://reviews.llvm.org/D7648
Files:
clang-tidy/readability/CMakeLists.txt
clang-tidy/readability/ReadabilityTidyModule.cpp
clang-tidy/readability/SimplifyBooleanExpr.cpp
clang-tidy/readability/SimplifyBooleanExpr.h
test/clang-tidy/readability-simplify-bool-expr.cpp
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
Index: clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tidy/readability/CMakeLists.txt
+++ clang-tidy/readability/CMakeLists.txt
@@ -9,6 +9,7 @@
ReadabilityTidyModule.cpp
RedundantSmartptrGet.cpp
ShrinkToFitCheck.cpp
+ SimplifyBooleanExpr.cpp
LINK_LIBS
clangAST
Index: clang-tidy/readability/ReadabilityTidyModule.cpp
===================================================================
--- clang-tidy/readability/ReadabilityTidyModule.cpp
+++ clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -16,6 +16,7 @@
#include "FunctionSize.h"
#include "RedundantSmartptrGet.h"
#include "ShrinkToFitCheck.h"
+#include "SimplifyBooleanExpr.h"
namespace clang {
namespace tidy {
@@ -36,6 +37,8 @@
"readability-redundant-smartptr-get");
CheckFactories.registerCheck<ShrinkToFitCheck>(
"readability-shrink-to-fit");
+ CheckFactories.registerCheck<SimplifyBooleanExpr>(
+ "readability-simplify-boolean-expr");
}
};
Index: clang-tidy/readability/SimplifyBooleanExpr.cpp
===================================================================
--- /dev/null
+++ clang-tidy/readability/SimplifyBooleanExpr.cpp
@@ -0,0 +1,269 @@
+//===--- SimplifyBooleanExpr.cpp clang-tidy ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SimplifyBooleanExpr.h"
+#include "clang/Lex/Lexer.h"
+
+#include <string>
+
+using namespace clang;
+using namespace clang::ast_matchers;
+
+namespace {
+
+StringRef getText(const MatchFinder::MatchResult &Result, SourceRange Range) {
+ return Lexer::getSourceText(CharSourceRange::getTokenRange(Range),
+ *Result.SourceManager,
+ Result.Context->getLangOpts());
+}
+
+template <typename T>
+StringRef getText(const MatchFinder::MatchResult &Result, T &Node) {
+ return getText(Result, Node.getSourceRange());
+}
+
+const char RightExpressionId[] = "bool-op-expr-yields-expr";
+const char LeftExpressionId[] = "expr-op-bool-yields-expr";
+const char NegatedRightExpressionId[] = "bool-op-expr-yields-not-expr";
+const char NegatedLeftExpressionId[] = "expr-op-bool-yields-not-expr";
+const char ConditionThenStmtId[] = "if-bool-yields-then";
+const char ConditionElseStmtId[] = "if-bool-yields-else";
+const char TernaryId[] = "ternary-bool-yields-condition";
+const char TernaryNegatedId[] = "ternary-bool-yields-not-condition";
+const char IfReturnsBoolId[] = "if-return";
+const char IfReturnsNotBoolId[] = "if-not-return";
+const char ThenLiteralId[] = "then-literal";
+
+const char IfStmtId[] = "if";
+const char LHSId[] = "lhs-expr";
+const char RHSId[] = "rhs-expr";
+
+const char SimplifyOperatorDiagnostic[] =
+ "redundant boolean literal supplied to boolean operator";
+const char SimplifyConditionDiagnostic[] =
+ "redundant boolean literal in if statement condition";
+
+const CXXBoolLiteralExpr *getBoolLiteral(const MatchFinder::MatchResult &Result,
+ const char *const Id) {
+ const auto Literal = Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(Id);
+ return Literal &&
+ Result.SourceManager->isMacroBodyExpansion(
+ Literal->getLocStart())
+ ? nullptr
+ : Literal;
+}
+
+internal::VariadicOperatorMatcher<internal::BindableMatcher<Stmt> &,
+ internal::BindableMatcher<Stmt>>
+ReturnsBool(bool Value, char const *const Id = nullptr) {
+ auto SimpleReturnsBool =
+ returnStmt(has(boolLiteral(equals(Value)).bind(Id ? Id : "ignored")));
+ return anyOf(SimpleReturnsBool,
+ compoundStmt(statementCountIs(1), has(SimpleReturnsBool)));
+}
+
+} // namespace
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void SimplifyBooleanExpr::matchBoolBinOpExpr(MatchFinder *Finder, bool Value,
+ const char *const OperatorName,
+ const char *const BooleanId) {
+ Finder->addMatcher(
+ binaryOperator(isExpansionInMainFile(), hasOperatorName(OperatorName),
+ hasLHS(allOf(boolLiteral(equals(Value)).bind(BooleanId),
+ expr().bind(LHSId))),
+ hasRHS(expr().bind(RHSId)),
+ unless(hasRHS(hasDescendant(boolLiteral())))),
+ this);
+}
+
+void SimplifyBooleanExpr::matchExprBinOpBool(MatchFinder *Finder, bool Value,
+ const char *const OperatorName,
+ const char *const BooleanId) {
+ Finder->addMatcher(
+ binaryOperator(isExpansionInMainFile(), hasOperatorName(OperatorName),
+ hasLHS(expr().bind(LHSId)), unless(hasLHS(boolLiteral())),
+ unless(hasLHS(hasDescendant(boolLiteral()))),
+ hasRHS(boolLiteral(equals(Value)).bind(BooleanId)),
+ hasRHS(expr().bind(RHSId))),
+ this);
+}
+
+void SimplifyBooleanExpr::matchBoolCompOpExpr(MatchFinder *Finder, bool Value,
+ const char *const OperatorName,
+ const char *const BooleanId) {
+ Finder->addMatcher(
+ binaryOperator(
+ isExpansionInMainFile(), hasOperatorName(OperatorName),
+ hasLHS(hasDescendant(boolLiteral(equals(Value)).bind(BooleanId))),
+ hasLHS(expr().bind(LHSId)), hasRHS(expr().bind(RHSId)),
+ unless(hasRHS(hasDescendant(boolLiteral())))),
+ this);
+}
+
+void SimplifyBooleanExpr::matchExprCompOpBool(MatchFinder *Finder, bool Value,
+ const char *const OperatorName,
+ const char *const BooleanId) {
+ Finder->addMatcher(
+ binaryOperator(
+ isExpansionInMainFile(), hasOperatorName(OperatorName),
+ unless(hasLHS(hasDescendant(boolLiteral()))),
+ hasLHS(expr().bind(LHSId)), hasRHS(expr().bind(RHSId)),
+ hasRHS(hasDescendant(boolLiteral(equals(Value)).bind(BooleanId)))),
+ this);
+}
+
+void SimplifyBooleanExpr::matchBoolCondition(MatchFinder *Finder, bool Value,
+ const char *const BooleanId) {
+ Finder->addMatcher(ifStmt(isExpansionInMainFile(),
+ hasCondition(boolLiteral(equals(Value))
+ .bind(BooleanId))).bind(IfStmtId),
+ this);
+}
+
+void SimplifyBooleanExpr::matchTernaryResult(MatchFinder *Finder, bool Value,
+ const char *const TernaryId) {
+ Finder->addMatcher(
+ conditionalOperator(isExpansionInMainFile(),
+ hasTrueExpression(boolLiteral(equals(Value))),
+ hasFalseExpression(boolLiteral(equals(!Value))))
+ .bind(TernaryId),
+ this);
+}
+
+void SimplifyBooleanExpr::matchIfReturnsBool(MatchFinder *Finder, bool Value,
+ char const *const Id) {
+ Finder->addMatcher(ifStmt(isExpansionInMainFile(),
+ hasThen(ReturnsBool(Value, ThenLiteralId)),
+ hasElse(ReturnsBool(!Value))).bind(Id),
+ this);
+}
+
+void SimplifyBooleanExpr::registerMatchers(MatchFinder *Finder) {
+ matchBoolBinOpExpr(Finder, true, "&&", RightExpressionId);
+ matchBoolBinOpExpr(Finder, false, "||", RightExpressionId);
+ matchExprBinOpBool(Finder, false, "&&", RightExpressionId);
+ matchExprBinOpBool(Finder, true, "||", RightExpressionId);
+ matchBoolCompOpExpr(Finder, true, "==", RightExpressionId);
+ matchBoolCompOpExpr(Finder, false, "!=", RightExpressionId);
+
+ matchExprBinOpBool(Finder, true, "&&", LeftExpressionId);
+ matchExprBinOpBool(Finder, false, "||", LeftExpressionId);
+ matchBoolBinOpExpr(Finder, false, "&&", LeftExpressionId);
+ matchBoolBinOpExpr(Finder, true, "||", LeftExpressionId);
+ matchExprCompOpBool(Finder, true, "==", LeftExpressionId);
+ matchExprCompOpBool(Finder, false, "!=", LeftExpressionId);
+
+ matchBoolCompOpExpr(Finder, false, "==", NegatedRightExpressionId);
+ matchBoolCompOpExpr(Finder, true, "!=", NegatedRightExpressionId);
+
+ matchExprCompOpBool(Finder, false, "==", NegatedLeftExpressionId);
+ matchExprCompOpBool(Finder, true, "!=", NegatedLeftExpressionId);
+
+ matchBoolCondition(Finder, true, ConditionThenStmtId);
+ matchBoolCondition(Finder, false, ConditionElseStmtId);
+
+ matchTernaryResult(Finder, true, TernaryId);
+ matchTernaryResult(Finder, false, TernaryNegatedId);
+
+ matchIfReturnsBool(Finder, true, IfReturnsBoolId);
+ matchIfReturnsBool(Finder, false, IfReturnsNotBoolId);
+}
+
+void SimplifyBooleanExpr::check(const MatchFinder::MatchResult &Result) {
+ if (auto LeftRemoved = getBoolLiteral(Result, RightExpressionId)) {
+ replaceWithExpression(Result, LeftRemoved, false);
+ } else if (auto RightRemoved = getBoolLiteral(Result, LeftExpressionId)) {
+ replaceWithExpression(Result, RightRemoved, true);
+ } else if (auto NegatedLeftRemoved =
+ getBoolLiteral(Result, NegatedRightExpressionId)) {
+ replaceWithExpression(Result, NegatedLeftRemoved, false, true);
+ } else if (auto NegatedRightRemoved =
+ getBoolLiteral(Result, NegatedLeftExpressionId)) {
+ replaceWithExpression(Result, NegatedRightRemoved, true, true);
+ } else if (auto TrueConditionRemoved =
+ getBoolLiteral(Result, ConditionThenStmtId)) {
+ replaceWithThenStatement(Result, TrueConditionRemoved);
+ } else if (auto FalseConditionRemoved =
+ getBoolLiteral(Result, ConditionElseStmtId)) {
+ replaceWithElseStatement(Result, FalseConditionRemoved);
+ } else if (auto Ternary =
+ Result.Nodes.getNodeAs<ConditionalOperator>(TernaryId)) {
+ replaceWithCondition(Result, Ternary);
+ } else if (auto TernaryNegated = Result.Nodes.getNodeAs<ConditionalOperator>(
+ TernaryNegatedId)) {
+ replaceWithCondition(Result, TernaryNegated, true);
+ } else if (auto If = Result.Nodes.getNodeAs<IfStmt>(IfReturnsBoolId)) {
+ replaceWithReturnCondition(Result, If);
+ } else if (auto IfNot = Result.Nodes.getNodeAs<IfStmt>(IfReturnsNotBoolId)) {
+ replaceWithReturnCondition(Result, IfNot, true);
+ }
+}
+
+void SimplifyBooleanExpr::replaceWithExpression(
+ const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXBoolLiteralExpr *BoolLiteral, bool UseLHS, bool Negated) {
+ const auto LHS = Result.Nodes.getNodeAs<Expr>(LHSId);
+ const auto RHS = Result.Nodes.getNodeAs<Expr>(RHSId);
+ std::string Replacement =
+ ((Negated ? "!" : "") + getText(Result, *(UseLHS ? LHS : RHS))).str();
+ SourceLocation Start = LHS->getLocStart();
+ SourceLocation End = RHS->getLocEnd();
+ diag(BoolLiteral->getLocStart(), SimplifyOperatorDiagnostic)
+ << FixItHint::CreateReplacement(SourceRange(Start, End), Replacement);
+}
+
+void SimplifyBooleanExpr::replaceWithThenStatement(
+ const MatchFinder::MatchResult &Result,
+ const CXXBoolLiteralExpr *TrueConditionRemoved) {
+ const auto IfStatement = Result.Nodes.getNodeAs<IfStmt>(IfStmtId);
+ diag(TrueConditionRemoved->getLocStart(), SimplifyConditionDiagnostic)
+ << FixItHint::CreateReplacement(IfStatement->getSourceRange(),
+ getText(Result, *IfStatement->getThen()));
+}
+
+void SimplifyBooleanExpr::replaceWithElseStatement(
+ const MatchFinder::MatchResult &Result,
+ const CXXBoolLiteralExpr *FalseConditionRemoved) {
+ const auto IfStatement = Result.Nodes.getNodeAs<IfStmt>(IfStmtId);
+ const auto ElseStatement = IfStatement->getElse();
+ diag(FalseConditionRemoved->getLocStart(), SimplifyConditionDiagnostic)
+ << FixItHint::CreateReplacement(
+ IfStatement->getSourceRange(),
+ ElseStatement ? getText(Result, *ElseStatement) : "");
+}
+
+void SimplifyBooleanExpr::replaceWithCondition(
+ const MatchFinder::MatchResult &Result, const ConditionalOperator *Ternary,
+ const bool Negated) {
+ std::string Replacement =
+ ((Negated ? "!" : "") + getText(Result, *Ternary->getCond())).str();
+ diag(Ternary->getTrueExpr()->getLocStart(),
+ "redundant boolean literal in ternary expression result")
+ << FixItHint::CreateReplacement(Ternary->getSourceRange(), Replacement);
+}
+
+void SimplifyBooleanExpr::replaceWithReturnCondition(
+ const MatchFinder::MatchResult &Result, const IfStmt *If, bool Negated) {
+ StringRef Terminator = isa<CompoundStmt>(If->getElse()) ? ";" : "";
+ std::string Replacement =
+ ("return " + StringRef(Negated ? "!" : "") + "(" +
+ getText(Result, *If->getCond()) + ")" + Terminator).str();
+ const auto Start =
+ Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(ThenLiteralId)->getLocStart();
+ diag(Start, "redundant boolean literal in conditional return statement")
+ << FixItHint::CreateReplacement(If->getSourceRange(), Replacement);
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/readability/SimplifyBooleanExpr.h
===================================================================
--- /dev/null
+++ clang-tidy/readability/SimplifyBooleanExpr.h
@@ -0,0 +1,92 @@
+//===--- SimplifyBooleanExpr.h clang-tidy -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \brief Looks for boolean expressions involving boolean constants and
+// simplifies them to use the appropriate boolean expression directly.
+///
+/// Examples:
+/// `if (b == true)` becomes `if (b)`
+/// `if (b == false)` becomes `if (!b)`
+/// `if (b && true)` becomes `if (b)`
+/// `if (b && false)` becomes `if (false)`
+/// `if (b || true)` becomes `if (true)`
+/// `if (b || false)` becomes `if (b)`
+/// `e ? true : false` becomes `e`
+/// `e ? false : true` becomes `!e`
+/// `if (true) t(); else f();` becomes `t();`
+/// `if (false) t(); else f();` becomes `f();`
+/// `if (e) return true; else return false;` becomes `return (e);`
+/// `if (e) return false; else return true;` becomes `return !(e);`
+///
+class SimplifyBooleanExpr : public ClangTidyCheck {
+public:
+ SimplifyBooleanExpr(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ void matchBoolBinOpExpr(ast_matchers::MatchFinder *Finder, bool Value,
+ const char *OperatorName, const char *BooleanId);
+
+ void matchExprBinOpBool(ast_matchers::MatchFinder *Finder, bool Value,
+ const char *OperatorName, const char *BooleanId);
+
+ void matchBoolCompOpExpr(ast_matchers::MatchFinder *Finder, bool Value,
+ const char *OperatorName, const char *BooleanId);
+
+ void matchExprCompOpBool(ast_matchers::MatchFinder *Finder, bool Value,
+ const char *OperatorName, const char *BooleanId);
+
+ void matchBoolCondition(ast_matchers::MatchFinder *Finder, bool Value,
+ const char *BooleanId);
+
+ void matchTernaryResult(ast_matchers::MatchFinder *Finder, bool Value,
+ const char *TernaryId);
+
+ void matchIfReturnsBool(ast_matchers::MatchFinder *Finder, bool Value,
+ char const *Id);
+
+ void
+ replaceWithExpression(const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXBoolLiteralExpr *BoolLiteral, bool UseLHS,
+ bool Negated = false);
+
+ void
+ replaceWithThenStatement(const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXBoolLiteralExpr *BoolLiteral);
+
+ void
+ replaceWithElseStatement(const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXBoolLiteralExpr *FalseConditionRemoved);
+
+ void
+ replaceWithCondition(const ast_matchers::MatchFinder::MatchResult &Result,
+ const ConditionalOperator *Ternary,
+ bool Negated = false);
+
+ void replaceWithReturnCondition(
+ const ast_matchers::MatchFinder::MatchResult &Result, const IfStmt *If,
+ bool Negated = false);
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_SIMPLIFY_BOOLEAN_EXPR_H
Index: test/clang-tidy/readability-simplify-bool-expr.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/readability-simplify-bool-expr.cpp
@@ -0,0 +1,440 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s readability-simplify-boolean-expr %t
+// REQUIRES: shell
+
+bool a1 = false;
+
+//=-=-=-=-=-=-= operator ==
+bool aa = false == a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant boolean literal supplied to boolean operator [readability-simplify-boolean-expr]
+// CHECK-FIXES: {{^bool aa = !a1;$}}
+bool ab = true == a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ab = a1;$}}
+bool a2 = a1 == false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a2 = !a1;$}}
+bool a3 = a1 == true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a3 = a1;$}}
+
+//=-=-=-=-=-=-= operator !=
+bool n1 = a1 != false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n1 = a1;$}}
+bool n2 = a1 != true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n2 = !a1;$}}
+bool n3 = false != a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n3 = a1;$}}
+bool n4 = true != a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool n4 = !a1;$}}
+
+//=-=-=-=-=-=-= operator ||
+bool a4 = a1 || false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a4 = a1;$}}
+bool a5 = a1 || true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a5 = true;$}}
+bool a6 = false || a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a6 = a1;$}}
+bool a7 = true || a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a7 = true;$}}
+
+//=-=-=-=-=-=-= operator &&
+bool a8 = a1 && false;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// X-CHECK-FIXES: {{^bool a8 = false;$}}
+bool a9 = a1 && true;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool a9 = a1;$}}
+bool ac = false && a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ac = false;$}}
+bool ad = true && a1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
+// CHECK-FIXES: {{^bool ad = a1;$}}
+
+void if_with_bool_literal_condition()
+{
+ int i = 0;
+ if (false) {
+ i = 1;
+ } else {
+ i = 2;
+ }
+ i = 3;
+ // CHECK-MESSAGES: :[[@LINE-6]]:9: warning: {{.*}} in if statement condition
+ // CHECK-FIXES: {{^ int i = 0;$}}
+ // CHECK-FIXES-NEXT: {{^ {$}}
+ // CHECK-FIXES-NEXT: {{^ i = 2;$}}
+ // CHECK-FIXES-NEXT: {{^ }$}}
+ // CHECK-FIXES-NEXT: {{^ i = 3;$}}
+
+ i = 4;
+ if (true) {
+ i = 5;
+ } else {
+ i = 6;
+ }
+ i = 7;
+ // CHECK-MESSAGES: :[[@LINE-6]]:9: warning: {{.*}} in if statement condition
+ // CHECK-FIXES: {{^ i = 4;$}}
+ // CHECK-FIXES-NEXT: {{^ {$}}
+ // CHECK-FIXES-NEXT: {{^ i = 5;$}}
+ // CHECK-FIXES-NEXT: {{^ }$}}
+ // CHECK-FIXES-NEXT: {{^ i = 7;$}}
+
+ i = 8;
+ if (false) {
+ i = 9;
+ }
+ i = 11;
+ // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in if statement condition
+ // CHECK-FIXES: {{^ i = 8;$}}
+ // CHECK-FIXES-NEXT: {{^ $}}
+ // CHECK-FIXES-NEXT: {{^ i = 11;$}}
+}
+
+void operator_equals()
+{
+ int i = 0;
+ bool b1 = (i > 2);
+ if (b1 == true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b1\) {$}}
+ i = 5;
+ } else {
+ i = 6;
+ }
+ bool b2 = (i > 4);
+ if (b2 == false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!b2\) {$}}
+ i = 7;
+ } else {
+ i = 9;
+ }
+ bool b3 = (i > 6);
+ if (true == b3) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b3\) {$}}
+ i = 10;
+ } else {
+ i = 11;
+ }
+ bool b4 = (i > 8);
+ if (false == b4) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!b4\) {$}}
+ i = 12;
+ } else {
+ i = 13;
+ }
+}
+
+void operator_or()
+{
+ int i = 0;
+ bool b5 = (i > 10);
+ if (b5 || false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b5\) {$}}
+ i = 14;
+ } else {
+ i = 15;
+ }
+ bool b6 = (i > 10);
+ if (b6 || true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true\) {$}}
+ i = 16;
+ } else {
+ i = 17;
+ }
+ bool b7 = (i > 10);
+ if (false || b7) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(b7\) {$}}
+ i = 18;
+ } else {
+ i = 19;
+ }
+ bool b8 = (i > 10);
+ if (true || b8) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // X-CHECK-FIXES: {{^ if \(true\) {$}}
+ i = 20;
+ } else {
+ i = 21;
+ }
+}
+
+void operator_and()
+{
+ int i = 0;
+ bool b9 = (i > 20);
+ if (b9 && false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false\) {$}}
+ i = 22;
+ } else {
+ i = 23;
+ }
+ bool ba = (i > 20);
+ if (ba && true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(ba\) {$}}
+ i = 24;
+ } else {
+ i = 25;
+ }
+ bool bb = (i > 20);
+ if (false && bb) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false\) {$}}
+ i = 26;
+ } else {
+ i = 27;
+ }
+ bool bc = (i > 20);
+ if (true && bc) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(bc\) {$}}
+ i = 28;
+ } else {
+ i = 29;
+ }
+}
+
+void ternary_operator()
+{
+ int i = 0;
+ bool bd = (i > 20) ? true : false;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: {{.*}} in ternary expression result
+ // CHECK-FIXES: {{^ bool bd = \(i > 20\);$}}
+ bool be = (i > 20) ? false : true;
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: {{.*}} in ternary expression result
+ // CHECK-FIXES: {{^ bool be = !\(i > 20\);$}}
+}
+
+void operator_not_equal()
+{
+ int i = 0;
+ bool bf = (i > 20);
+ if (false != bf) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(bf\) {$}}
+ i = 30;
+ } else {
+ i = 31;
+ }
+ bool bg = (i > 20);
+ if (true != bg) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!bg\) {$}}
+ i = 32;
+ } else {
+ i = 33;
+ }
+ bool bh = (i > 20);
+ if (bh != false) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(bh\) {$}}
+ i = 34;
+ } else {
+ i = 35;
+ }
+ bool bi = (i > 20);
+ if (bi != true) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(!bi\) {$}}
+ i = 36;
+ } else {
+ i = 37;
+ }
+}
+
+void nested_booleans()
+{
+ if (false || (true || false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false \|\| \(true\)\) {$}}
+ }
+ if (true && (true || false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true && \(true\)\) {$}}
+ }
+ if (false || (true && false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(false \|\| \(false\)\) {$}}
+ }
+ if (true && (true && false)) {
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}} to boolean operator
+ // CHECK-FIXES: {{^ if \(true && \(false\)\) {$}}
+ }
+}
+
+static constexpr bool truthy()
+{
+ return true;
+}
+
+#define HAS_XYZ_FEATURE true
+
+void macros_and_constexprs(int i = 0)
+{
+ bool b = (i == 1);
+ if (b && truthy()) {
+ // leave this alone; if you want it simplified, then you should
+ // inline the constexpr function first.
+ i = 1;
+ }
+ i = 2;
+ if (b && HAS_XYZ_FEATURE) {
+ // leave this alone; if you want it simplified, then you should
+ // inline the macro first.
+ i = 3;
+ }
+ i = 4;
+}
+
+bool conditional_return_statements(int i)
+{
+ if (i == 0) return true; else return false;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:24: warning: redundant boolean literal in conditional return statement
+// CHECK-FIXES: {{^}} return (i == 0);{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_return_statements_then_expr(int i, int j)
+{
+ if (i == j) return (i == 0); else return false;
+}
+
+bool conditional_return_statements_else_expr(int i, int j)
+{
+ if (i == j) return true; else return (i == 0);
+}
+
+bool negated_conditional_return_statements(int i)
+{
+ if (i == 0) return false; else return true;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:24: warning: redundant boolean literal in conditional return statement
+// CHECK-FIXES: {{^}} return !(i == 0);{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_compound_return_statements(int i)
+{
+ if (i == 1) {
+ return true;
+ } else {
+ return false;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:16: warning: redundant boolean literal in conditional return statement
+// CHECK-FIXES: {{^{$}}
+// CHECK-FIXES-NEXT: {{^}} return (i == 1);{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool negated_conditional_compound_return_statements(int i)
+{
+ if (i == 1) {
+ return false;
+ } else {
+ return true;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:16: warning: redundant boolean literal in conditional return statement
+// CHECK-FIXES: {{^{$}}
+// CHECK-FIXES-NEXT: {{^}} return !(i == 1);{{$}}
+// CHECK-FIXES-NEXT: {{^}$}}
+
+bool conditional_return_statements_side_effects_then(int i)
+{
+ if (i == 2) {
+ macros_and_constexprs();
+ return true;
+ } else
+ return false;
+}
+
+bool negated_conditional_return_statements_side_effects_then(int i)
+{
+ if (i == 2) {
+ macros_and_constexprs();
+ return false;
+ } else
+ return true;
+}
+
+bool conditional_return_statements_side_effects_else(int i)
+{
+ if (i == 2)
+ return true;
+ else {
+ macros_and_constexprs();
+ return false;
+ }
+}
+
+bool negated_conditional_return_statements_side_effects_else(int i)
+{
+ if (i == 2)
+ return false;
+ else {
+ macros_and_constexprs();
+ return true;
+ }
+}
+
+void lambda_conditional_return_statements()
+{
+ auto lambda = [](int n) -> bool { if (n > 0) return true; else return false; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:57: warning: redundant boolean literal in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda = [](int n) -> bool { return (n > 0); };{{$}}
+
+ auto lambda2 = [](int n) -> bool {
+ if (n > 0) {
+ return true;
+ } else {
+ return false;
+ }
+ };
+ // CHECK-MESSAGES: :[[@LINE-5]]:20: warning: redundant boolean literal in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda2 = [](int n) -> bool {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} return (n > 0);{{$}}
+ // CHECK-FIXES-NEXT: {{^}} };{{$}}
+
+ auto lambda3 = [](int n) -> bool { if (n > 0) {macros_and_constexprs(); return true; } else return false; };
+
+ auto lambda4 = [](int n) -> bool {
+ if (n > 0)
+ return true;
+ else {
+ macros_and_constexprs();
+ return false;
+ }
+ };
+
+ auto lambda5 = [](int n) -> bool { if (n > 0) return false; else return true; };
+ // CHECK-MESSAGES: :[[@LINE-1]]:58: warning: redundant boolean literal in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda5 = [](int n) -> bool { return !(n > 0); };{{$}}
+
+ auto lambda6 = [](int n) -> bool {
+ if (n > 0) {
+ return false;
+ } else {
+ return true;
+ }
+ };
+ // CHECK-MESSAGES: :[[@LINE-5]]:20: warning: redundant boolean literal in conditional return statement
+ // CHECK-FIXES: {{^}} auto lambda6 = [](int n) -> bool {{{$}}
+ // CHECK-FIXES-NEXT: {{^}} return !(n > 0);{{$}}
+ // CHECK-FIXES-NEXT: {{^}} };{{$}}
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits