Hi alexfh,

This changeset extends the simplify boolean expression check in `clang-tidy` to 
simplify `if (e) return true; return false;` to `return e;` (note the lack of 
an else clause on the if statement.)

http://reviews.llvm.org/D9810

Files:
  clang-tidy/readability/SimplifyBooleanExprCheck.cpp
  clang-tidy/readability/SimplifyBooleanExprCheck.h
  test/clang-tidy/readability-simplify-bool-expr.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: clang-tidy/readability/SimplifyBooleanExprCheck.cpp
===================================================================
--- clang-tidy/readability/SimplifyBooleanExprCheck.cpp
+++ clang-tidy/readability/SimplifyBooleanExprCheck.cpp
@@ -48,6 +48,11 @@
 const char IfAssignBoolId[] = "if-assign";
 const char IfAssignNotBoolId[] = "if-assign-not";
 const char IfAssignObjId[] = "if-assign-obj";
+const char CompoundId[] = "compound";
+const char CompoundIfReturnsBoolId[] = "compound-if";
+const char CompoundReturnId[] = "compound-return";
+const char CompoundBoolId[] = "compound-bool";
+const char CompoundNotBoolId[] = "compound-bool-not";
 
 const char IfStmtId[] = "if";
 const char LHSId[] = "lhs-expr";
@@ -57,6 +62,8 @@
     "redundant boolean literal supplied to boolean operator";
 const char SimplifyConditionDiagnostic[] =
     "redundant boolean literal in if statement condition";
+const char SimplifyConditionalReturnDiagnostic[] =
+    "redundant boolean literal in conditional return statement";
 
 const CXXBoolLiteralExpr *getBoolLiteral(const MatchFinder::MatchResult &Result,
                                          StringRef Id) {
@@ -67,9 +74,11 @@
              : Literal;
 }
 
-internal::Matcher<Stmt> ReturnsBool(bool Value, StringRef Id = "") {
-  auto SimpleReturnsBool = returnStmt(
-      has(boolLiteral(equals(Value)).bind(Id.empty() ? "ignored" : Id)));
+internal::Matcher<Stmt> returnsBool(bool Value, StringRef Id = "") {
+  auto SimpleReturnsBool =
+      returnStmt(
+          has(boolLiteral(equals(Value)).bind(Id.empty() ? "ignored" : Id)))
+          .bind("returns-bool");
   return anyOf(SimpleReturnsBool,
                compoundStmt(statementCountIs(1), has(SimpleReturnsBool)));
 }
@@ -108,16 +117,31 @@
       StringRef NegatedOperator = negatedOperator(BinOp);
       if (!NegatedOperator.empty()) {
         return (getText(Result, *BinOp->getLHS()) + " " + NegatedOperator +
-                " " + getText(Result, *BinOp->getRHS()))
-            .str();
+                " " + getText(Result, *BinOp->getRHS())).str();
       }
     }
   }
   StringRef Text = getText(Result, *E);
   return (Negated ? (needsParensAfterUnaryNegation(E) ? "!(" + Text + ")"
                                                       : "!" + Text)
-                  : Text)
-      .str();
+                  : Text).str();
+}
+
+bool isFollowedBy(const CompoundStmt *Compound, const Stmt *Before,
+                  const Stmt *After) {
+  if (Compound->size() < 2) {
+    return false;
+  }
+
+  CompoundStmt::const_body_iterator BeforeIt = Compound->body_begin();
+  CompoundStmt::const_body_iterator AfterIt = Compound->body_begin();
+  for (++AfterIt; AfterIt != Compound->body_end(); ++BeforeIt, ++AfterIt) {
+    if (*BeforeIt == Before && *AfterIt == After) {
+      return true;
+    }
+  }
+
+  return false;
 }
 
 } // namespace
@@ -200,8 +224,8 @@
 void SimplifyBooleanExprCheck::matchIfReturnsBool(MatchFinder *Finder,
                                                   bool Value, StringRef Id) {
   Finder->addMatcher(ifStmt(isExpansionInMainFile(),
-                            hasThen(ReturnsBool(Value, ThenLiteralId)),
-                            hasElse(ReturnsBool(!Value))).bind(Id),
+                            hasThen(returnsBool(Value, ThenLiteralId)),
+                            hasElse(returnsBool(!Value))).bind(Id),
                      this);
 }
 
@@ -225,6 +249,20 @@
       this);
 }
 
+void SimplifyBooleanExprCheck::matchCompoundIfReturnsBool(MatchFinder *Finder,
+                                                          bool Value,
+                                                          StringRef Id) {
+  Finder->addMatcher(
+      compoundStmt(
+          allOf(hasAnySubstatement(
+                    ifStmt(
+                        hasThen(returnsBool(Value, CompoundId)),
+                        unless(hasElse(stmt()))).bind(CompoundIfReturnsBoolId)),
+                hasAnySubstatement(returnStmt(has(boolLiteral(equals(!Value))))
+                                       .bind(CompoundReturnId)))).bind(Id),
+      this);
+}
+
 void SimplifyBooleanExprCheck::registerMatchers(MatchFinder *Finder) {
   matchBoolBinOpExpr(Finder, true, "&&", RightExpressionId);
   matchBoolBinOpExpr(Finder, false, "||", RightExpressionId);
@@ -257,6 +295,9 @@
 
   matchIfAssignsBool(Finder, true, IfAssignBoolId);
   matchIfAssignsBool(Finder, false, IfAssignNotBoolId);
+
+  matchCompoundIfReturnsBool(Finder, true, CompoundBoolId);
+  matchCompoundIfReturnsBool(Finder, false, CompoundNotBoolId);
 }
 
 void SimplifyBooleanExprCheck::check(const MatchFinder::MatchResult &Result) {
@@ -296,6 +337,12 @@
   } else if (const auto *IfAssignNot =
                  Result.Nodes.getNodeAs<IfStmt>(IfAssignNotBoolId)) {
     replaceWithAssignment(Result, IfAssignNot, true);
+  } else if (const auto *Compound =
+                 Result.Nodes.getNodeAs<CompoundStmt>(CompoundBoolId)) {
+    replaceCompoundReturnWithCondition(Result, Compound);
+  } else if (const auto *Compound =
+                 Result.Nodes.getNodeAs<CompoundStmt>(CompoundNotBoolId)) {
+    replaceCompoundReturnWithCondition(Result, Compound, true);
   }
 }
 
@@ -349,10 +396,28 @@
   std::string Replacement = ("return " + Condition + Terminator).str();
   SourceLocation Start =
       Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(ThenLiteralId)->getLocStart();
-  diag(Start, "redundant boolean literal in conditional return statement")
+  diag(Start, SimplifyConditionalReturnDiagnostic)
       << FixItHint::CreateReplacement(If->getSourceRange(), Replacement);
 }
 
+void SimplifyBooleanExprCheck::replaceCompoundReturnWithCondition(
+    const MatchFinder::MatchResult &Result, const CompoundStmt *Compound,
+    bool Negated) {
+  const auto *IfRet = Result.Nodes.getNodeAs<IfStmt>(CompoundIfReturnsBoolId);
+  const auto *Ret = Result.Nodes.getNodeAs<ReturnStmt>(CompoundReturnId);
+
+  if (isFollowedBy(Compound, IfRet, Ret)) {
+    const Expr *Condition = IfRet->getCond();
+    const auto *Lit = Result.Nodes.getNodeAs<CXXBoolLiteralExpr>(CompoundId);
+    assert(Lit);
+    std::string Replacement =
+        "return " + replacementExpression(Result, Negated, Condition);
+    diag(Lit->getLocStart(), SimplifyConditionalReturnDiagnostic)
+        << FixItHint::CreateReplacement(
+            SourceRange(IfRet->getLocStart(), Ret->getLocEnd()), Replacement);
+  }
+}
+
 void SimplifyBooleanExprCheck::replaceWithAssignment(
     const MatchFinder::MatchResult &Result, const IfStmt *IfAssign,
     bool Negated) {
Index: clang-tidy/readability/SimplifyBooleanExprCheck.h
===================================================================
--- clang-tidy/readability/SimplifyBooleanExprCheck.h
+++ clang-tidy/readability/SimplifyBooleanExprCheck.h
@@ -34,6 +34,8 @@
 /// `if (e) return false; else return true;`   becomes `return !(e);`
 /// `if (e) b = true; else b = false;`         becomes `b = e;`
 /// `if (e) b = false; else b = true;`         becomes `b = !(e);`
+/// `if (e) return true; return false;`        becomes `return e;`
+/// `if (e) return false; return true;`        becomes `return !e;`
 ///
 class SimplifyBooleanExprCheck : public ClangTidyCheck {
 public:
@@ -67,6 +69,9 @@
   void matchIfAssignsBool(ast_matchers::MatchFinder *Finder, bool Value,
                           StringRef Id);
 
+  void matchCompoundIfReturnsBool(ast_matchers::MatchFinder *Finder, bool Value,
+                                  StringRef Id);
+
   void
   replaceWithExpression(const ast_matchers::MatchFinder::MatchResult &Result,
                         const CXXBoolLiteralExpr *BoolLiteral, bool UseLHS,
@@ -92,6 +97,10 @@
   void
   replaceWithAssignment(const ast_matchers::MatchFinder::MatchResult &Result,
                         const IfStmt *If, bool Negated = false);
+
+  void replaceCompoundReturnWithCondition(
+      const ast_matchers::MatchFinder::MatchResult &Result,
+      const CompoundStmt *Compound, bool Negated = false);
 };
 
 } // namespace readability
Index: test/clang-tidy/readability-simplify-bool-expr.cpp
===================================================================
--- test/clang-tidy/readability-simplify-bool-expr.cpp
+++ test/clang-tidy/readability-simplify-bool-expr.cpp
@@ -541,3 +541,45 @@
   } else
     f = false;
 }
+
+bool simple_if_return_return(int i) {
+  if (i > 10)
+    return true;
+  return false;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool simple_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^  return i > 10;$}}
+// CHECK-FIXES: {{^}}}{{$}}
+
+bool simple_if_return_return_negated(int i) {
+  if (i > 10)
+    return false;
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool simple_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^  return i <= 10;$}}
+// CHECK-FIXES: {{^}}}{{$}}
+
+bool complex_if_return_return(int i) {
+  if (i > 10) {
+    return true;
+  }
+  return false;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_if_return_return(int i) {{{$}}
+// CHECK-FIXES: {{^  return i > 10;$}}
+// CHECK-FIXES: {{^}}}{{$}}
+
+bool complex_if_return_return_negated(int i) {
+  if (i > 10) {
+    return false;
+  }
+  return true;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
+// CHECK-FIXES: {{^}}bool complex_if_return_return_negated(int i) {{{$}}
+// CHECK-FIXES: {{^  return i <= 10;$}}
+// CHECK-FIXES: {{^}}}{{$}}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to