baloghadamsoftware updated this revision to Diff 285309.
baloghadamsoftware added a comment.

Updated according to the comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D81272/new/

https://reviews.llvm.org/D81272

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/clang-tidy/misc/RedundantConditionCheck.cpp
  clang-tools-extra/clang-tidy/misc/RedundantConditionCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-redundant-condition.rst
  clang-tools-extra/test/clang-tidy/checkers/misc-redundant-condition.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc-redundant-condition.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc-redundant-condition.cpp
@@ -0,0 +1,1153 @@
+// RUN: %check_clang_tidy %s misc-redundant-condition %t
+
+extern unsigned peopleInTheBuilding;
+extern unsigned fireFighters;
+
+bool isBurning();
+bool isReallyBurning();
+bool isCollapsing();
+void tryToExtinguish(bool&);
+void tryPutFireOut();
+bool callTheFD();
+void scream();
+
+bool someOtherCondition();
+
+//===--- Basic Positives --------------------------------------------------===//
+
+void positive_direct() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (onFire)
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+    }
+  }
+}
+
+void positive_direct_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire && peopleInTheBuilding > 0) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: if ( peopleInTheBuilding > 0) {
+      scream();
+    }
+  }
+}
+
+void positive_indirect_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (onFire && peopleInTheBuilding > 0) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if ( peopleInTheBuilding > 0) {
+        scream();
+      }
+    }
+  }
+}
+
+void positive_direct_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (peopleInTheBuilding > 0 && onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: if (peopleInTheBuilding > 0 ) {
+      scream();
+    }
+  }
+}
+
+void positive_indirect_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (peopleInTheBuilding > 0 && onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if (peopleInTheBuilding > 0 ) {
+        scream();
+      }
+    }
+  }
+}
+
+void positive_direct_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire || isCollapsing()) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (onFire || isCollapsing()) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (isCollapsing() || onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (isCollapsing() || onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_outer_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+    // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_outer_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      if (onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_outer_and_lhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (onFire && peopleInTheBuilding > 0) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: if ( peopleInTheBuilding > 0) {
+      scream();
+    }
+  }
+}
+
+void positive_indirect_outer_and_lhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      if (onFire && peopleInTheBuilding > 0) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if ( peopleInTheBuilding > 0) {
+        scream();
+      }
+    }
+  }
+}
+
+void positive_direct_outer_and_lhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (peopleInTheBuilding > 0 && onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: if (peopleInTheBuilding > 0 ) {
+      scream();
+    }
+  }
+}
+
+void positive_indirect_outer_and_lhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      if (peopleInTheBuilding > 0 && onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if (peopleInTheBuilding > 0 ) {
+        scream();
+      }
+    }
+  }
+}
+
+void positive_direct_outer_and_lhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (onFire || isCollapsing()) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_outer_and_lhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      if (onFire || isCollapsing()) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+    // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_outer_and_lhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (isCollapsing() || onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_outer_and_lhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      if (isCollapsing() || onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_outer_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_outer_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      if (onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_outer_and_rhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (onFire && peopleInTheBuilding > 0) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: if ( peopleInTheBuilding > 0) {
+      scream();
+    }
+  }
+}
+
+void positive_indirect_outer_and_rhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      if (onFire && peopleInTheBuilding > 0) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if ( peopleInTheBuilding > 0) {
+        scream();
+      }
+    }
+  }
+}
+
+void positive_direct_inner_outer_and_rhs_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (peopleInTheBuilding > 0 && onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if (peopleInTheBuilding > 0 ) {
+      scream();
+    }
+  }
+}
+
+void positive_indirect_outer_and_rhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      if (peopleInTheBuilding > 0 && onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: if (peopleInTheBuilding > 0 ) {
+        scream();
+      }
+    }
+  }
+}
+
+void positive_direct_outer_and_rhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (onFire || isCollapsing()) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_outer_and_rhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      if (onFire || isCollapsing()) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+void positive_direct_outer_and_rhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (isCollapsing() || onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_indirect_outer_and_rhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      if (isCollapsing() || onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+  }
+}
+
+//===--- Basic Negatives --------------------------------------------------===//
+
+void negative_direct() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (onFire && peopleInTheBuilding > 0) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire && peopleInTheBuilding > 0) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire && peopleInTheBuilding > 0) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (peopleInTheBuilding > 0 && onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (peopleInTheBuilding > 0 && onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (peopleInTheBuilding > 0 && onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (onFire || isCollapsing()) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire || isCollapsing()) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire || isCollapsing()) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (isCollapsing() || onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (isCollapsing() || onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (isCollapsing() || onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_lhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (onFire && peopleInTheBuilding > 0) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_lhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire && peopleInTheBuilding > 0) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_lhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire && peopleInTheBuilding > 0) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_lhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (peopleInTheBuilding > 0 && onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_lhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (peopleInTheBuilding > 0 && onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_lhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (peopleInTheBuilding > 0 && onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_lhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (onFire || isCollapsing()) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_lhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire || isCollapsing()) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_lhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire || isCollapsing()) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_lhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (isCollapsing() || onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_lhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (isCollapsing() || onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_lhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (isCollapsing() || onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_rhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (onFire && peopleInTheBuilding > 0) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_rhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire && peopleInTheBuilding > 0) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_rhs_inner_and_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire && peopleInTheBuilding > 0) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_inner_outer_and_rhs_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (peopleInTheBuilding > 0 && onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_rhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (peopleInTheBuilding > 0 && onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_rhs_inner_and_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (peopleInTheBuilding > 0 && onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_rhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (onFire || isCollapsing()) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_rhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (onFire || isCollapsing()) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_rhs_inner_or_lhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (onFire || isCollapsing()) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_direct_outer_and_rhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (isCollapsing() || onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_indirect_outer_and_rhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    tryToExtinguish(onFire);
+    if (someOtherCondition()) {
+      if (isCollapsing() || onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_indirect2_outer_and_rhs_inner_or_rhs() {
+  bool onFire = isBurning();
+  if (fireFighters < 10 && onFire) {
+    if (someOtherCondition()) {
+      tryToExtinguish(onFire);
+      if (isCollapsing() || onFire) {
+        // NO-MESSAGE: fire may have been extinguished
+        scream();
+      }
+    }
+  }
+}
+
+void negative_reassigned() {
+  bool onFire = isBurning();
+  if (onFire) {
+    onFire = isReallyBurning();
+    if (onFire) {
+      // NO-MESSAGE: it was a false alarm then
+      scream();
+    }
+  }
+}
+
+//===--- Special Positives ------------------------------------------------===//
+
+// Condition variable mutated in or after the inner loop
+
+void positive_direct_mutated_after_inner() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+    tryToExtinguish(onFire);
+  }
+}
+
+void positive_indirect_mutated_after_inner() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+    }
+    tryToExtinguish(onFire);
+  }
+}
+
+void positive_indirect2_mutated_after_inner() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (someOtherCondition()) {
+      if (onFire) {
+        // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant condition 'onFire' [misc-redundant-condition]
+        // CHECK-FIXES: {{^\ *$}}
+        scream();
+      }
+      // CHECK-FIXES: {{^\ *$}}
+      tryToExtinguish(onFire);
+    }
+  }
+}
+
+void positive_mutated_in_inner() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: {{^\ *$}}
+      tryToExtinguish(onFire);
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_or_lhs_with_side_effect() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (callTheFD() || onFire) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: callTheFD() ;
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+void positive_or_rhs_with_side_effect() {
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire || callTheFD()) {
+      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHECK-FIXES: callTheFD();
+      scream();
+    }
+    // CHECK-FIXES: {{^\ *$}}
+  }
+}
+
+// GNU Expression Statements
+
+void do_something();
+
+void positive_gnu_expression_statement() {
+  bool onFire = isBurning();
+  if (({ do_something(); onFire; })) {
+    if (({ do_something(); onFire; })) {
+      // FIXME: Handle GNU epxression statements
+      // CHECK-MESSAGES-NOT: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHCK-FIXES-NOT: do_something();
+      scream();
+    }
+  }
+}
+
+// Comma after Condition
+
+void positive_comma_after_condition() {
+  bool onFire = isBurning();
+  if (do_something(), onFire) {
+    if (do_something(), onFire) {
+      // FIXME: Handle comma operator
+      // CHECK-MESSAGES-NOT: :[[@LINE-1]]:5: warning: redundant condition 'onFire' [misc-redundant-condition]
+      // CHCK-FIXES-NOT: do_something();
+      scream();
+    }
+  }
+}
+
+//===--- Special Negatives ------------------------------------------------===//
+
+// Aliasing
+
+void negative_mutated_by_ptr() {
+  bool onFire = isBurning();
+  bool *firePtr = &onFire;
+  if (onFire) {
+    tryToExtinguish(*firePtr);
+    if (onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+void negative_mutated_by_ref() {
+  bool onFire = isBurning();
+  bool &fireRef = onFire;
+  if (onFire) {
+    tryToExtinguish(fireRef);
+    if (onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+// Volatile
+
+void negatvie_volatile() {
+  bool volatile onFire = isBurning();
+  if (onFire) {
+    if (onFire) {
+      // NO-MESSAGE: maybe some other thread extinguished the fire
+      scream();
+    }
+  }
+}
+
+void negative_else_branch(bool isHot) {
+  bool onFire = isBurning();
+  if (onFire) {
+    tryPutFireOut();
+  } else {
+    if (isHot && onFire) {
+      // NO-MESSAGE: new check is in the `else` branch
+      // FIXME: handle `else` branches and negated conditions
+      scream();
+    }
+  }
+}
+
+// GNU Expression Statements
+
+void negative_gnu_expression_statement() {
+  bool onFire = isBurning();
+  if (({ do_something(); onFire; })) {
+    tryToExtinguish(onFire);
+    if (({ do_something(); onFire; })) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
+
+// Comma after Condition
+
+void negative_comma_after_condition() {
+  bool onFire = isBurning();
+  if (do_something(), onFire) {
+    tryToExtinguish(onFire);
+    if (do_something(), onFire) {
+      // NO-MESSAGE: fire may have been extinguished
+      scream();
+    }
+  }
+}
Index: clang-tools-extra/docs/clang-tidy/checks/misc-redundant-condition.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-redundant-condition.rst
@@ -0,0 +1,80 @@
+.. title:: clang-tidy - misc-redundant-condition
+
+misc-redundant-condition
+========================
+
+Finds condition variables in nested ``if`` statements that were also checked in
+the outer ``if`` statement and were not changed.
+
+Simple example:
+
+.. code-block:: c
+
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire)
+      scream();
+  }
+
+Here `onFire` is checked both in the outer ``if`` and the inner ``if`` statement
+without a possible change between the two checks. The check warns for this code
+and suggests removal of the second checking of variable `onFire`.
+
+The checker also detects redundant condition checks if the condition variable
+is an operand of a logical "and" (``&&``) or a logical "or" (``||``) operator:
+
+.. code-block:: c
+
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire && peopleInTheBuilding > 0)
+      scream();
+  }
+
+.. code-block:: c
+
+  bool onFire = isBurning();
+  if (onFire) {
+    if (onFire || isCollapsing())
+      scream();
+  }
+
+In the first case (logical "and") the suggested fix is to remove the redundant
+condition variable and keep the other side of the ``&&``. In the second case
+(logical "or") the whole ``if`` is removed similarily to the simple case on the
+top.
+
+The condition of the outer ``if`` statement may also be a logical "and" (``&&``)
+expression:
+
+.. code-block:: c
+
+  bool onFire = isBurning();
+  if (onFire && fireFighters < 10) {
+    if (someOtherCondition()) {
+      if (onFire)
+        scream();
+    }
+  }
+
+The error is also detected if both the outer statement is a logical "and"
+(``&&``) and the inner statement is a logical "and" (``&&``) or "or" (``||``).
+The inner ``if`` statement does not have to be a direct descendant of the outer
+one.
+
+No error is detected if the condition variable may have been changed between the
+two checks:
+
+.. code-block:: c
+
+  bool onFire = isBurning();
+  if (onFire) {
+    tryToExtinguish(onFire);
+    if (onFire && peopleInTheBuilding > 0)
+      scream();
+  }
+
+Every possible change is considered, thus if the condition variable is not
+a local variable of the function, it is a volatile or it has an alias (pointer
+or reference) then no warning is issued.
+
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -200,6 +200,7 @@
    `misc-no-recursion <misc-no-recursion.html>`_,
    `misc-non-copyable-objects <misc-non-copyable-objects.html>`_,
    `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_,
+   `misc-redundant-condition <misc-redundant-condition.html>`_, "Yes"
    `misc-redundant-expression <misc-redundant-expression.html>`_, "Yes"
    `misc-static-assert <misc-static-assert.html>`_, "Yes"
    `misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_,
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -67,7 +67,11 @@
 Improvements to clang-tidy
 --------------------------
 
-The improvements are...
+- New :doc:`misc-redundant-condition
+  <clang-tidy/checks/misc-redundant-condition>` check.
+
+  Finds condition variables in nested ``if`` statements that were also checked
+  in the outer ``if`` statement and were not changed.
 
 Improvements to include-fixer
 -----------------------------
Index: clang-tools-extra/clang-tidy/misc/RedundantConditionCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/RedundantConditionCheck.h
@@ -0,0 +1,35 @@
+//===--- RedundantConditionCheck.h - clang-tidy -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANTCONDITIONCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANTCONDITIONCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds condition variables in nested `if` statements that were also checked
+/// in the outer `if` statement and were not changed.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-redundant-condition.html
+class RedundantConditionCheck : public ClangTidyCheck {
+public:
+  RedundantConditionCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANTCONDITIONCHECK_H
Index: clang-tools-extra/clang-tidy/misc/RedundantConditionCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/RedundantConditionCheck.cpp
@@ -0,0 +1,153 @@
+//===--- RedundantConditionCheck.cpp - clang-tidy -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantConditionCheck.h"
+#include "../utils/Aliasing.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+using clang::tidy::utils::hasPtrOrReferenceInFunc;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+static const char CondVarStr[] = "cond_var";
+static const char OuterIfStr[] = "outer_if";
+static const char InnerIfStr[] = "inner_if";
+static const char FuncStr[] = "func";
+
+/// Returns whether `Var` is changed in `S` before `NextS`.
+static bool isChangedBefore(const Stmt *S, const Stmt *NextS,
+                            const VarDecl *Var, ASTContext *Context) {
+  ExprMutationAnalyzer MutAn(*S, *Context);
+  const auto &SM = Context->getSourceManager();
+  const Stmt *MutS = MutAn.findMutation(Var);
+  return MutS &&
+         SM.isBeforeInTranslationUnit(MutS->getEndLoc(), NextS->getBeginLoc());
+}
+
+void RedundantConditionCheck::registerMatchers(MatchFinder *Finder) {
+  const auto ImmutableVar =
+      varDecl(anyOf(parmVarDecl(), hasLocalStorage()), hasType(isInteger()),
+              unless(hasType(isVolatileQualified())))
+          .bind(CondVarStr);
+  Finder->addMatcher(
+      ifStmt(
+          hasCondition(ignoringParenImpCasts(anyOf(
+              declRefExpr(hasDeclaration(ImmutableVar)),
+              binaryOperator(hasOperatorName("&&"),
+                             hasEitherOperand(ignoringParenImpCasts(declRefExpr(
+                                 hasDeclaration(ImmutableVar)))))))),
+          hasThen(hasDescendant(
+              ifStmt(hasCondition(ignoringParenImpCasts(
+                         anyOf(declRefExpr(hasDeclaration(
+                                   varDecl(equalsBoundNode(CondVarStr)))),
+                               binaryOperator(
+                                   hasAnyOperatorName("&&", "||"),
+                                   hasEitherOperand(ignoringParenImpCasts(
+                                       declRefExpr(hasDeclaration(varDecl(
+                                           equalsBoundNode(CondVarStr)))))))))))
+                  .bind(InnerIfStr))),
+          forFunction(functionDecl().bind(FuncStr)))
+          .bind(OuterIfStr),
+      this);
+  // FIXME: Handle longer conjunctive and disjunctive clauses.
+}
+
+void RedundantConditionCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *OuterIf = Result.Nodes.getNodeAs<IfStmt>(OuterIfStr);
+  const auto *InnerIf = Result.Nodes.getNodeAs<IfStmt>(InnerIfStr);
+  const auto *CondVar = Result.Nodes.getNodeAs<VarDecl>(CondVarStr);
+  const auto *Func = Result.Nodes.getNodeAs<FunctionDecl>(FuncStr);
+
+  // If the variable has an alias then it can be changed by that alias as well.
+  // FIXME: could potentially support tracking pointers and references in the
+  // future to improve catching true positives through aliases.
+  if (hasPtrOrReferenceInFunc(Func, CondVar))
+    return;
+
+  if (isChangedBefore(OuterIf->getThen(), InnerIf, CondVar, Result.Context))
+    return;
+
+  auto Diag = diag(InnerIf->getBeginLoc(), "redundant condition %0") << CondVar;
+
+  // For standalone condition variables and for "or" binary operations we simply
+  // remove the inner `if`.
+  const auto *BinOpCond = dyn_cast<BinaryOperator>(InnerIf->getCond());
+  if (isa<DeclRefExpr>(InnerIf->getCond()->IgnoreParenImpCasts()) ||
+      (BinOpCond && BinOpCond->getOpcode() == BO_LOr)) {
+    SourceLocation IfBegin = InnerIf->getBeginLoc();
+    const Stmt *Body = InnerIf->getThen();
+    const Expr *OtherSide = nullptr;
+    if (BinOpCond) {
+      const auto *LeftDRE =
+          dyn_cast<DeclRefExpr>(BinOpCond->getLHS()->IgnoreParenImpCasts());
+      if (LeftDRE && LeftDRE->getDecl() == CondVar)
+        OtherSide = BinOpCond->getRHS();
+      else
+        OtherSide = BinOpCond->getLHS();
+    }
+
+    SourceLocation IfEnd = Body->getBeginLoc().getLocWithOffset(-1);
+
+    // For compound statements also remove the left brace.
+    if (isa<CompoundStmt>(Body))
+      IfEnd = Body->getBeginLoc();
+
+    // If the other side has side effects then keep it.
+    if (OtherSide && OtherSide->HasSideEffects(*Result.Context)) {
+      SourceLocation BeforeOtherSide =
+          OtherSide->getBeginLoc().getLocWithOffset(-1);
+      SourceLocation AfterOtherSide =
+          Lexer::findNextToken(OtherSide->getEndLoc(), *Result.SourceManager,
+                               getLangOpts())
+              ->getLocation();
+      Diag << FixItHint::CreateRemoval(
+                  CharSourceRange::getTokenRange(IfBegin, BeforeOtherSide))
+           << FixItHint::CreateInsertion(AfterOtherSide, ";")
+           << FixItHint::CreateRemoval(
+                  CharSourceRange::getTokenRange(AfterOtherSide, IfEnd));
+    } else {
+      Diag << FixItHint::CreateRemoval(
+          CharSourceRange::getTokenRange(IfBegin, IfEnd));
+    }
+
+    // For comound statements also remove the right brace at the end.
+    if (isa<CompoundStmt>(Body))
+      Diag << FixItHint::CreateRemoval(
+          CharSourceRange::getTokenRange(Body->getEndLoc(), Body->getEndLoc()));
+
+    // For "and" binary operations we remove the "and" operation with the
+    // condition variable from the inner if.
+  } else {
+    const auto *CondOp = cast<BinaryOperator>(InnerIf->getCond());
+    const auto *LeftDRE =
+        dyn_cast<DeclRefExpr>(CondOp->getLHS()->IgnoreParenImpCasts());
+    if (LeftDRE && LeftDRE->getDecl() == CondVar) {
+      SourceLocation BeforeRHS =
+          CondOp->getRHS()->getBeginLoc().getLocWithOffset(-1);
+      Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
+          CondOp->getLHS()->getBeginLoc(), BeforeRHS));
+    } else {
+      SourceLocation AfterLHS =
+          Lexer::findNextToken(CondOp->getLHS()->getEndLoc(),
+                               *Result.SourceManager, getLangOpts())
+              ->getLocation();
+      Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
+          AfterLHS, CondOp->getRHS()->getEndLoc()));
+    }
+  }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -15,6 +15,7 @@
 #include "NoRecursionCheck.h"
 #include "NonCopyableObjects.h"
 #include "NonPrivateMemberVariablesInClassesCheck.h"
+#include "RedundantConditionCheck.h"
 #include "RedundantExpressionCheck.h"
 #include "StaticAssertCheck.h"
 #include "ThrowByValueCatchByReferenceCheck.h"
@@ -41,6 +42,8 @@
         "misc-non-copyable-objects");
     CheckFactories.registerCheck<NonPrivateMemberVariablesInClassesCheck>(
         "misc-non-private-member-variables-in-classes");
+    CheckFactories.registerCheck<RedundantConditionCheck>(
+        "misc-redundant-condition");
     CheckFactories.registerCheck<RedundantExpressionCheck>(
         "misc-redundant-expression");
     CheckFactories.registerCheck<StaticAssertCheck>("misc-static-assert");
Index: clang-tools-extra/clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -11,6 +11,7 @@
   NoRecursionCheck.cpp
   NonCopyableObjects.cpp
   NonPrivateMemberVariablesInClassesCheck.cpp
+  RedundantConditionCheck.cpp
   RedundantExpressionCheck.cpp
   StaticAssertCheck.cpp
   ThrowByValueCatchByReferenceCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to