[clang-tools-extra] f3c1d28 - [clang-tidy] Extend SimplifyBooleanExpr demorgan support.

Nathan James via cfe-commits cfe-commits at lists.llvm.org
Wed May 25 05:09:12 PDT 2022


Author: Nathan James
Date: 2022-05-25T13:09:00+01:00
New Revision: f3c1d281767a5849b9f3e712e3c3406bd9410c81

URL: https://github.com/llvm/llvm-project/commit/f3c1d281767a5849b9f3e712e3c3406bd9410c81
DIFF: https://github.com/llvm/llvm-project/commit/f3c1d281767a5849b9f3e712e3c3406bd9410c81.diff

LOG: [clang-tidy] Extend SimplifyBooleanExpr demorgan support.

Adds an option SimplifyDemorganRelaxed which, when enabled, will transform negated conjunctions or disjunctions when neither operand is a negation.
Default value is `false`.

Reviewed By: LegalizeAdulthood

Differential Revision: https://reviews.llvm.org/D126162

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
    clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h
    clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst
    clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-demorgan.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
index f35f7839dc257..8ae990a929dfd 100644
--- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.cpp
@@ -558,7 +558,8 @@ class SimplifyBooleanExprCheck::Visitor : public RecursiveASTVisitor<Visitor> {
     if (!BinaryOp || !BinaryOp->isLogicalOp() ||
         !BinaryOp->getType()->isBooleanType())
       return Base::TraverseUnaryOperator(Op);
-    if (checkEitherSide(BinaryOp, isUnaryLNot) ||
+    if (Check->SimplifyDeMorganRelaxed ||
+        checkEitherSide(BinaryOp, isUnaryLNot) ||
         checkEitherSide(BinaryOp,
                         [](const Expr *E) { return nestedDemorgan(E, 1); })) {
       if (Check->reportDeMorgan(Context, Op, BinaryOp, !IsProcessing, parent(),
@@ -584,7 +585,13 @@ SimplifyBooleanExprCheck::SimplifyBooleanExprCheck(StringRef Name,
       ChainedConditionalReturn(Options.get("ChainedConditionalReturn", false)),
       ChainedConditionalAssignment(
           Options.get("ChainedConditionalAssignment", false)),
-      SimplifyDeMorgan(Options.get("SimplifyDeMorgan", true)) {}
+      SimplifyDeMorgan(Options.get("SimplifyDeMorgan", true)),
+      SimplifyDeMorganRelaxed(Options.get("SimplifyDeMorganRelaxed", false)) {
+  if (SimplifyDeMorganRelaxed && !SimplifyDeMorgan)
+    configurationDiag("%0: 'SimplifyDeMorganRelaxed' cannot be enabled "
+                      "without 'SimplifyDeMorgan' enabled")
+        << Name;
+}
 
 static bool containsBoolLiteral(const Expr *E) {
   if (!E)
@@ -667,6 +674,7 @@ void SimplifyBooleanExprCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "ChainedConditionalAssignment",
                 ChainedConditionalAssignment);
   Options.store(Opts, "SimplifyDeMorgan", SimplifyDeMorgan);
+  Options.store(Opts, "SimplifyDeMorganRelaxed", SimplifyDeMorganRelaxed);
 }
 
 void SimplifyBooleanExprCheck::registerMatchers(MatchFinder *Finder) {

diff  --git a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h
index 72d8f3354b890..8da20f37b975e 100644
--- a/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/SimplifyBooleanExprCheck.h
@@ -69,6 +69,7 @@ class SimplifyBooleanExprCheck : public ClangTidyCheck {
   const bool ChainedConditionalReturn;
   const bool ChainedConditionalAssignment;
   const bool SimplifyDeMorgan;
+  const bool SimplifyDeMorganRelaxed;
 };
 
 } // namespace readability

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst
index 240e7be64ad45..f25d4c418695f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability-simplify-boolean-expr.rst
@@ -96,3 +96,23 @@ Options
 
    If `true`, DeMorgan's Theorem will be applied to simplify negated
    conjunctions and disjunctions.  Default is `true`.
+
+.. option:: SimplifyDeMorganRelaxed
+
+   If `true`, :option:`SimplifyDeMorgan` will also transform negated 
+   conjunctions and disjunctions where there is no negation on either operand. 
+   Default is `false`.
+
+   When Enabled:
+
+   .. code-block::
+
+      bool X = !(A && B)
+      bool Y = !(A || B)
+
+   Would be transformed to:
+
+   .. code-block::
+
+      bool X = !A || !B
+      bool Y = !A && !B

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-demorgan.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-demorgan.cpp
index 12a9eb65352d8..6787273daa8c5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-demorgan.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr-demorgan.cpp
@@ -1,9 +1,30 @@
 // RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
 
+// Check when we can convert !(A Op B) -> !A InvOp !B.
+// RUN: %check_clang_tidy -check-suffixes=",RELAXED" %s \
+// RUN: readability-simplify-boolean-expr %t -- -config="{CheckOptions: [{ \
+// RUN: key: "readability-simplify-boolean-expr.SimplifyDeMorganRelaxed", value: true}]}" --
+
+// Verify warning issued when invalid options are specified.
+// RUN: clang-tidy %s -checks=-*,readability-simplify-boolean-expr -config="{CheckOptions: [ \
+// RUN:   {key: readability-simplify-boolean-expr.SimplifyDeMorgan, value: false}, \
+// RUN:   {key: readability-simplify-boolean-expr.SimplifyDeMorganRelaxed, value: true}]}" \
+// RUN: -- 2>&1 | FileCheck %s -check-prefix=CHECK-BAD-CONFIG \
+// RUN:       -implicit-check-not="{{warning|error}}:"
+
+// CHECK-BAD-CONFIG: warning: readability-simplify-boolean-expr: 'SimplifyDeMorganRelaxed' cannot be enabled without 'SimplifyDeMorgan' enabled
 void eat(bool);
 
 void foo(bool A1, bool A2, bool A3, bool A4) {
   bool X;
+
+  X = !(A1 && A2);
+  X = !(A1 || A2);
+  // CHECK-MESSAGES-RELAXED: :[[@LINE-2]]:7: warning: boolean expression can be simplified by DeMorgan's theorem
+  // CHECK-MESSAGES-RELAXED: :[[@LINE-2]]:7: warning: boolean expression can be simplified by DeMorgan's theorem
+  // CHECK-FIXES-RELAXED: X = !A1 || !A2;
+  // CHECK-FIXES-NEXT-RELAXED: X = !A1 && !A2;
+
   X = !(!A1 || A2);
   X = !(A1 || !A2);
   X = !(!A1 || !A2);


        


More information about the cfe-commits mailing list