================
@@ -0,0 +1,392 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "BoolBitwiseOperationCheck.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/Expr.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Lexer.h"
+#include <array>
+#include <type_traits>
+#include <utility>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::misc {
+
+static constexpr std::array<std::pair<StringRef, StringRef>, 8U>
+    OperatorsTransformation{{{"|", "||"},
+                             {"|=", "||"},
+                             {"&", "&&"},
+                             {"&=", "&&"},
+                             {"bitand", "and"},
+                             {"and_eq", "and"},
+                             {"bitor", "or"},
+                             {"or_eq", "or"}}};
+
+static constexpr std::integral_constant<bool, true> RespectStrictMode{};
+static constexpr std::integral_constant<bool, false> IgnoreStrictMode{};
+
+static StringRef translate(StringRef Value) {
+  for (const auto &[Bitwise, Logical] : OperatorsTransformation)
+    if (Value == Bitwise)
+      return Logical;
+
+  return {};
+}
+
+static bool isBitwiseOperation(StringRef Value) {
+  return llvm::is_contained(llvm::make_first_range(OperatorsTransformation),
+                            Value);
+}
+
+static std::optional<CharSourceRange>
+getOperatorTokenRangeForFixIt(const BinaryOperator *BinOp,
+                              const SourceManager &SM,
+                              const LangOptions &LangOpts) {
+  SourceLocation Loc = BinOp->getOperatorLoc();
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return std::nullopt;
+
+  Loc = SM.getSpellingLoc(Loc);
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return std::nullopt;
+
+  CharSourceRange TokenRange = CharSourceRange::getTokenRange(Loc);
+  if (TokenRange.isInvalid())
+    return std::nullopt;
+
+  return TokenRange;
+}
+
+static std::optional<SourceLocation>
+getSpellingLocationForFixIt(SourceLocation Loc, const SourceManager &SM) {
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return std::nullopt;
+
+  Loc = SM.getSpellingLoc(Loc);
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return std::nullopt;
+
+  return Loc;
+}
+
+static std::optional<SourceLocation>
+getEndOfTokenLocationForFixIt(SourceLocation Loc, const SourceManager &SM,
+                              const LangOptions &LangOpts) {
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return std::nullopt;
+
+  Loc = SM.getSpellingLoc(Loc);
+  if (Loc.isInvalid() || Loc.isMacroID())
+    return std::nullopt;
+
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts);
+  if (EndLoc.isInvalid() || EndLoc.isMacroID())
+    return std::nullopt;
+
+  return EndLoc;
+}
+
+/// Checks if all leaf nodes in a bitwise expression satisfy a given condition.
+///
+/// \param Expr The bitwise expression to check.
+/// \param Condition A function that checks if a leaf node satisfies the
+///                  desired condition.
+/// \returns true if the condition is satisfied according to the combiner 
logic.
+template <typename F>
+static bool leavesOfBitwiseSatisfy(const clang::Expr *Expr,
+                                   const F &Condition) {
+  // Strip away implicit casts and parentheses before checking the condition.
+  // This is important for cases like:
+  //   bool b1, b2;
+  //   bool Deprecated = 0xFFFFFFF8 & (b1 & b2);
+  // where the operands of the inner '&' are represented in the AST as
+  //   ImplicitCastExpr <int> (ImplicitCastExpr <bool> (DeclRefExpr 'bool'))
+  // and we still want to classify the leaves as boolean.
+  Expr = Expr->IgnoreParenImpCasts();
+
+  // For leaf nodes, check if the condition is satisfied after stripping
+  // implicit casts/parens.
+  if (Condition(Expr))
+    return true;
+
+  // If it's a binary operator, recursively check both operands.
+  if (const auto *BinOp = dyn_cast<clang::BinaryOperator>(Expr)) {
+    if (!isBitwiseOperation(BinOp->getOpcodeStr()))
+      return false;
+    return leavesOfBitwiseSatisfy(BinOp->getLHS(), Condition) &&
+           leavesOfBitwiseSatisfy(BinOp->getRHS(), Condition);
+  }
+
+  return false;
+}
+
+namespace {
+
+// FIXME: provide memoization for this matcher
+
+/// Custom matcher that checks if all leaf nodes in an bitwise expression
+/// satisfy the given inner matcher condition. This uses
+/// leavesOfBitwiseSatisfy to recursively check.
+///
+/// Example usage:
+///   expr(hasAllLeavesOfBitwiseSatisfying(hasType(booleanType())))
+AST_MATCHER_P(Expr, hasAllLeavesOfBitwiseSatisfying,
+              ast_matchers::internal::Matcher<Expr>, InnerMatcher) {
+  auto Condition = [&](const clang::Expr *E) -> bool {
+    return InnerMatcher.matches(*E, Finder, Builder);
+  };
+  return leavesOfBitwiseSatisfy(&Node, Condition);
+}
+
+AST_MATCHER_P(Expr, hasSideEffects, bool, IncludePossibleEffects) {
+  auto &Ctx = Finder->getASTContext();
+  return Node.HasSideEffects(Ctx, IncludePossibleEffects);
+}
+
+} // namespace
+
+BoolBitwiseOperationCheck::BoolBitwiseOperationCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      UnsafeMode(Options.get("UnsafeMode", false)),
+      IgnoreMacros(Options.get("IgnoreMacros", false)),
+      StrictMode(Options.get("StrictMode", true)),
+      BraceCompound(Options.get("BraceCompound", true)),
+      // Undocumented option for debugging purposes
+      IgnoreWarningsWithFixIt(Options.get("IgnoreWarningsWithFixIt", false)) {}
----------------
vbvictor wrote:

Should be removed, it will be present in `--dump-config`

https://github.com/llvm/llvm-project/pull/167552
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to