Corrected documentation comments.
Support simplification of `if (e) return true; else return false;`
Fixed formatting of diagnostic messages to be consistent with the rest of clang.
Eliminated duplication of warning messages in tests.
clang-format -style=LLVM applied to the new files
Prefer StringRefs over std::string.
Prefer auto when initializing variables.
Let the compiler decide what to inline.


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,324 @@
+//===--- 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 ast_matchers::MatchFinder::MatchResult &Result,
+                  SourceRange Range) {
+  return Lexer::getSourceText(CharSourceRange::getTokenRange(Range),
+                              *Result.SourceManager,
+                              Result.Context->getLangOpts());
+}
+
+template <typename T>
+StringRef getText(const ast_matchers::MatchFinder::MatchResult &Result,
+                  T &Node) {
+  return getText(Result, Node.getSourceRange());
+}
+
+const auto LeftBooleanLiteralId = "bool-op-expr-yields-bool";
+const auto RightExpressionId = "bool-op-expr-yields-expr";
+const auto RightBooleanLiteralId = "expr-op-bool-yields-bool";
+const auto LeftExpressionId = "expr-op-bool-yields-expr";
+const auto NegatedRightExpressionId = "bool-op-expr-yields-not-expr";
+const auto NegatedLeftExpressionId = "expr-op-bool-yields-not-expr";
+const auto ConditionThenStmtId = "if-bool-yields-then";
+const auto ConditionElseStmtId = "if-bool-yields-else";
+const auto TernaryId = "ternary-bool-yields-condition";
+const auto TernaryNegatedId = "ternary-bool-yields-not-condition";
+const auto IfReturnsBoolId = "if-return";
+const auto IfReturnsNotBoolId = "if-not-return";
+const auto ThenLiteralId = "then-literal";
+
+const auto IfStmtId = "if";
+const auto ExpressionId = "expr";
+
+const auto SimplifyOperatorDiagnostic =
+    "redundant boolean literal supplied to boolean operator";
+const auto SimplifyConditionDiagnostic =
+    "redundant boolean literal in if statement condition";
+
+CXXBoolLiteralExpr const *getBoolLiteral(MatchFinder::MatchResult const &Result,
+                                         const char *const Id) {
+  CXXBoolLiteralExpr const *Literal =
+      Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(Id);
+  return Literal &&
+                 Result.SourceManager->isMacroBodyExpansion(
+                     Literal->getLocStart())
+             ? nullptr
+             : Literal;
+}
+
+internal::BindableMatcher<clang::Stmt>
+SimpleReturnsBool(bool Value, char const *const Id = nullptr) {
+  return returnStmt(has(boolLiteral(equals(Value)).bind(Id ? Id : "ignored")));
+}
+
+internal::VariadicOperatorMatcher<internal::BindableMatcher<clang::Stmt>,
+                                  internal::BindableMatcher<clang::Stmt>>
+ReturnsBool(bool Value, char const *const Id = nullptr) {
+  return anyOf(
+      SimpleReturnsBool(Value, Id),
+      compoundStmt(statementCountIs(1), has(SimpleReturnsBool(Value, Id))));
+}
+
+} // namespace
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void SimplifyBooleanExpr::matchBoolBinOpExpr(ast_matchers::MatchFinder *Finder,
+                                             bool Value,
+                                             const char *const OperatorName,
+                                             const char *const BooleanId) {
+  Finder->addMatcher(
+      binaryOperator(isExpansionInMainFile(), hasOperatorName(OperatorName),
+                     hasLHS(boolLiteral(equals(Value)).bind(BooleanId)),
+                     hasRHS(expr().bind(ExpressionId)),
+                     unless(hasRHS(hasDescendant(boolLiteral())))),
+      this);
+}
+
+void SimplifyBooleanExpr::matchExprBinOpBool(ast_matchers::MatchFinder *Finder,
+                                             bool Value,
+                                             const char *const OperatorName,
+                                             const char *const BooleanId) {
+  Finder->addMatcher(
+      binaryOperator(isExpansionInMainFile(), hasOperatorName(OperatorName),
+                     hasLHS(expr().bind(ExpressionId)),
+                     unless(hasLHS(boolLiteral())),
+                     unless(hasLHS(hasDescendant(boolLiteral()))),
+                     hasRHS(boolLiteral(equals(Value)).bind(BooleanId))),
+      this);
+}
+
+void SimplifyBooleanExpr::matchBoolCompOpExpr(ast_matchers::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))),
+          hasRHS(expr().bind(ExpressionId)),
+          unless(hasRHS(hasDescendant(boolLiteral())))),
+      this);
+}
+
+void SimplifyBooleanExpr::matchExprCompOpBool(ast_matchers::MatchFinder *Finder,
+                                              bool Value,
+                                              const char *const OperatorName,
+                                              const char *const BooleanId) {
+  Finder->addMatcher(
+      binaryOperator(
+          isExpansionInMainFile(), hasOperatorName(OperatorName),
+          hasLHS(expr().bind(ExpressionId)), unless(hasLHS(boolLiteral())),
+          unless(hasLHS(hasDescendant(boolLiteral()))),
+          hasRHS(hasDescendant(boolLiteral(equals(Value)).bind(BooleanId)))),
+      this);
+}
+
+void SimplifyBooleanExpr::matchBoolCondition(ast_matchers::MatchFinder *Finder,
+                                             bool Value,
+                                             const char *const BooleanId) {
+  Finder->addMatcher(ifStmt(isExpansionInMainFile(),
+                            hasCondition(boolLiteral(equals(Value))
+                                             .bind(BooleanId))).bind(IfStmtId),
+                     this);
+}
+
+void SimplifyBooleanExpr::matchTernaryResult(ast_matchers::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(ast_matchers::MatchFinder *Finder) {
+  matchBoolBinOpExpr(Finder, true, "&&", RightExpressionId);
+  matchBoolBinOpExpr(Finder, false, "||", RightExpressionId);
+  matchBoolCompOpExpr(Finder, true, "==", RightExpressionId);
+  matchBoolCompOpExpr(Finder, false, "!=", RightExpressionId);
+
+  matchBoolBinOpExpr(Finder, false, "&&", LeftBooleanLiteralId);
+  matchBoolBinOpExpr(Finder, true, "||", LeftBooleanLiteralId);
+
+  matchExprBinOpBool(Finder, false, "&&", RightBooleanLiteralId);
+  matchExprBinOpBool(Finder, true, "||", RightBooleanLiteralId);
+
+  matchExprBinOpBool(Finder, true, "&&", LeftExpressionId);
+  matchExprBinOpBool(Finder, false, "||", 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 ast_matchers::MatchFinder::MatchResult &Result) {
+  if (auto LeftRemoved = getBoolLiteral(Result, RightExpressionId)) {
+    replaceWithRightExpression(Result, LeftRemoved);
+  } else if (auto LeftReplacing =
+                 getBoolLiteral(Result, LeftBooleanLiteralId)) {
+    replaceWithLeftBooleanLiteral(Result, LeftReplacing);
+  } else if (auto RightReplacing =
+                 getBoolLiteral(Result, RightBooleanLiteralId)) {
+    replaceWithRightBooleanLiteral(Result, RightReplacing);
+  } else if (auto RightRemoved = getBoolLiteral(Result, LeftExpressionId)) {
+    replaceWithLeftExpression(Result, RightRemoved);
+  } else if (auto NegatedLeftRemoved =
+                 getBoolLiteral(Result, NegatedRightExpressionId)) {
+    replaceWithRightExpression(Result, NegatedLeftRemoved, true);
+  } else if (auto NegatedRightRemoved =
+                 getBoolLiteral(Result, NegatedLeftExpressionId)) {
+    replaceWithLeftExpression(Result, NegatedRightRemoved, "!");
+  } 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 If = Result.Nodes.getNodeAs<IfStmt>(IfReturnsNotBoolId)) {
+    replaceWithReturnCondition(Result, If, true);
+  }
+}
+
+void SimplifyBooleanExpr::replaceWithRightExpression(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    Expr const *BoolLiteral, const bool Negated) {
+  const auto Expression = Result.Nodes.getNodeAs<Expr>(ExpressionId);
+  const auto Replacement = (Negated ? "!" : "") + getText(Result, *Expression);
+  diag(BoolLiteral->getLocStart(), SimplifyOperatorDiagnostic)
+      << FixItHint::CreateReplacement(
+          SourceRange(BoolLiteral->getLocStart(), Expression->getLocEnd()),
+          Replacement.str());
+}
+
+void SimplifyBooleanExpr::replaceWithLeftBooleanLiteral(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    CXXBoolLiteralExpr const *BoolLiteral) {
+  const auto Expression = Result.Nodes.getNodeAs<Expr>(ExpressionId);
+  diag(BoolLiteral->getLocStart(), SimplifyOperatorDiagnostic)
+      << FixItHint::CreateReplacement(
+          SourceRange(BoolLiteral->getLocStart(), Expression->getLocEnd()),
+          getText(Result, *BoolLiteral));
+}
+
+void SimplifyBooleanExpr::replaceWithRightBooleanLiteral(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    CXXBoolLiteralExpr const *BoolLiteral) {
+  const auto Expression = Result.Nodes.getNodeAs<Expr>(ExpressionId);
+  diag(BoolLiteral->getLocStart(), SimplifyOperatorDiagnostic)
+      << FixItHint::CreateReplacement(
+          SourceRange(Expression->getLocStart(), BoolLiteral->getLocEnd()),
+          getText(Result, *BoolLiteral));
+}
+
+void SimplifyBooleanExpr::replaceWithLeftExpression(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    CXXBoolLiteralExpr const *BoolLiteral, const bool Negated) {
+  const auto Expression = Result.Nodes.getNodeAs<Expr>(ExpressionId);
+  const auto Replacement = (Negated ? "!" : "") + getText(Result, *Expression);
+  diag(BoolLiteral->getLocStart(), SimplifyOperatorDiagnostic)
+      << FixItHint::CreateReplacement(
+          SourceRange(Expression->getLocStart(), BoolLiteral->getLocEnd()),
+          Replacement.str());
+}
+
+void SimplifyBooleanExpr::replaceWithThenStatement(
+    const ast_matchers::MatchFinder::MatchResult &Result,
+    CXXBoolLiteralExpr const *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 ast_matchers::MatchFinder::MatchResult &Result,
+    CXXBoolLiteralExpr const *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 ast_matchers::MatchFinder::MatchResult &Result,
+    ConditionalOperator const *Ternary, const bool Negated) {
+  const auto Replacement =
+      (Negated ? "!" : "") + getText(Result, *Ternary->getCond());
+  diag(Ternary->getTrueExpr()->getLocStart(),
+       "redundant boolean literal in ternary expression result")
+      << FixItHint::CreateReplacement(Ternary->getSourceRange(),
+                                      Replacement.str());
+}
+
+void SimplifyBooleanExpr::replaceWithReturnCondition(
+    const ast_matchers::MatchFinder::MatchResult &Result, const IfStmt *If,
+    bool Negated) {
+  const auto Terminator =
+      (If->getElse()->getStmtClass() == Stmt::StmtClass::CompoundStmtClass)
+          ? ";"
+          : "";
+  const auto Replacement = "return " + StringRef(Negated ? "!" : "") + "(" +
+                           getText(Result, *If->getCond()) + ")" + Terminator;
+  const auto Start =
+      Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(ThenLiteralId)->getLocStart();
+  diag(Start, "redundant boolean literal in conditional return statement")
+      << FixItHint::CreateReplacement(If->getSourceRange(), Replacement.str());
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/readability/SimplifyBooleanExpr.h
===================================================================
--- /dev/null
+++ clang-tidy/readability/SimplifyBooleanExpr.h
@@ -0,0 +1,103 @@
+//===--- 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 *const Id);
+
+  void replaceWithRightExpression(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const Expr *BoolLiteral, bool Negate = false);
+
+  void replaceWithLeftBooleanLiteral(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const CXXBoolLiteralExpr *BoolLiteral);
+
+  void replaceWithRightBooleanLiteral(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const CXXBoolLiteralExpr *BoolLiteral);
+
+  void replaceWithLeftExpression(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const CXXBoolLiteralExpr *BoolLiteral, 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

Reply via email to