[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

Bhuminjay Soni via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 1 08:44:37 PDT 2024


https://github.com/11happy updated https://github.com/llvm/llvm-project/pull/84481

>From 8fdf6306085ed4cf0f77b7e718e374e9f65fedf9 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 8 Mar 2024 19:02:47 +0530
Subject: [PATCH 01/11] add clang-tidy check
 readability-math-missing-parentheses

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../clang-tidy/readability/CMakeLists.txt     |   1 +
 .../MathMissingParenthesesCheck.cpp           | 167 ++++++++++++++++++
 .../readability/MathMissingParenthesesCheck.h |  31 ++++
 .../readability/ReadabilityTidyModule.cpp     |   3 +
 clang-tools-extra/docs/ReleaseNotes.rst       |   6 +
 .../docs/clang-tidy/checks/list.rst           |   1 +
 .../readability/math-missing-parentheses.rst  |  19 ++
 .../readability/math-missing-parentheses.cpp  |  42 +++++
 8 files changed, 270 insertions(+)
 create mode 100644 clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
 create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index a6c8cbd8eb448a..0d4fa095501dfb 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -27,6 +27,7 @@ add_clang_library(clangTidyReadabilityModule
   IsolateDeclarationCheck.cpp
   MagicNumbersCheck.cpp
   MakeMemberFunctionConstCheck.cpp
+  MathMissingParenthesesCheck.cpp
   MisleadingIndentationCheck.cpp
   MisplacedArrayIndexCheck.cpp
   NamedParameterCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
new file mode 100644
index 00000000000000..d9574a9fb7a476
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -0,0 +1,167 @@
+//===--- MathMissingParenthesesCheck.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 "MathMissingParenthesesCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Preprocessor.h"
+#include <set>
+#include <stack>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),
+                                    hasDescendant(binaryOperator()))
+                         .bind("binOp"),
+                     this);
+}
+static int precedenceCheck(const char op) {
+  if (op == '/' || op == '*' || op == '%')
+    return 5;
+
+  else if (op == '+' || op == '-')
+    return 4;
+
+  else if (op == '&')
+    return 3;
+  else if (op == '^')
+    return 2;
+
+  else if (op == '|')
+    return 1;
+
+  else
+    return 0;
+}
+static bool isOperand(const char c) {
+  if (c >= 'a' && c <= 'z')
+    return true;
+  else if (c >= 'A' && c <= 'Z')
+    return true;
+  else if (c >= '0' && c <= '9')
+    return true;
+  else if (c == '$')
+    return true;
+  else
+    return false;
+}
+static bool conditionForNegative(const std::string s, int i,
+                                 const std::string CurStr) {
+  if (CurStr[0] == '-') {
+    if (i == 0) {
+      return true;
+    } else {
+      while (s[i - 1] == ' ') {
+        i--;
+      }
+      if (!isOperand(s[i - 1])) {
+        return true;
+      } else {
+        return false;
+      }
+    }
+  } else {
+    return false;
+  }
+}
+static std::string getOperationOrder(std::string s, std::set<char> &Operators) {
+  std::stack<std::string> StackOne;
+  std::string TempStr = "";
+  for (int i = 0; i < s.length(); i++) {
+    std::string CurStr = "";
+    CurStr += s[i];
+    if (CurStr == " ")
+      continue;
+    else {
+      if (isOperand(CurStr[0]) || conditionForNegative(s, i, CurStr)) {
+        while (i < s.length() && (isOperand(s[i]) || s[i] == '-')) {
+          if (s[i] == '-') {
+            TempStr += "$";
+          } else {
+            TempStr += CurStr;
+          }
+          i++;
+          CurStr = s[i];
+        }
+        TempStr += " ";
+      } else if (CurStr == "(") {
+        StackOne.push("(");
+      } else if (CurStr == ")") {
+        while (StackOne.top() != "(") {
+          TempStr += StackOne.top();
+          StackOne.pop();
+        }
+        StackOne.pop();
+      } else {
+        while (!StackOne.empty() && precedenceCheck(CurStr[0]) <=
+                                        precedenceCheck((StackOne.top())[0])) {
+          TempStr += StackOne.top();
+          StackOne.pop();
+        }
+        StackOne.push(CurStr);
+      }
+    }
+  }
+  while (!StackOne.empty()) {
+    TempStr += StackOne.top();
+    StackOne.pop();
+  }
+  std::stack<std::string> StackTwo;
+  for (int i = 0; i < TempStr.length(); i++) {
+    if (TempStr[i] == ' ')
+      continue;
+    else if (isOperand(TempStr[i])) {
+      std::string CurStr = "";
+      while (i < TempStr.length() && isOperand(TempStr[i])) {
+        if (TempStr[i] == '$') {
+          CurStr += "-";
+        } else {
+          CurStr += TempStr[i];
+        }
+        i++;
+      }
+      StackTwo.push(CurStr);
+    } else {
+      std::string OperandOne = StackTwo.top();
+      StackTwo.pop();
+      std::string OperandTwo = StackTwo.top();
+      StackTwo.pop();
+      Operators.insert(TempStr[i]);
+      StackTwo.push("(" + OperandTwo + " " + TempStr[i] + " " + OperandOne +
+                    ")");
+    }
+  }
+  return StackTwo.top();
+}
+void MathMissingParenthesesCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
+  if (!BinOp)
+    return;
+  clang::SourceManager &SM = *Result.SourceManager;
+  clang::LangOptions LO = Result.Context->getLangOpts();
+  clang::CharSourceRange Range =
+      clang::CharSourceRange::getTokenRange(BinOp->getSourceRange());
+  std::string Expression = clang::Lexer::getSourceText(Range, SM, LO).str();
+  std::set<char> Operators;
+  std::string FinalExpression = getOperationOrder(Expression, Operators);
+  if (Operators.size() > 1) {
+    if (FinalExpression.length() > 2) {
+      FinalExpression = FinalExpression.substr(1, FinalExpression.length() - 2);
+    }
+    diag(BinOp->getBeginLoc(),
+         "add parantheses to clarify the precedence of operations")
+        << FixItHint::CreateReplacement(Range, FinalExpression);
+  }
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
new file mode 100644
index 00000000000000..60b402831b45e0
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
@@ -0,0 +1,31 @@
+//===--- MathMissingParenthesesCheck.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_READABILITY_MATHMISSINGPARENTHESESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MATHMISSINGPARENTHESESCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+/// Checks for mathematical expressions that involve operators of different
+/// priorities.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/math-missing-parentheses.html
+class MathMissingParenthesesCheck : public ClangTidyCheck {
+public:
+  MathMissingParenthesesCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace clang::tidy::readability
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_MATHMISSINGPARENTHESESCHECK_H
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 87b299bf1ef1c5..b198153d27ee49 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -31,6 +31,7 @@
 #include "IsolateDeclarationCheck.h"
 #include "MagicNumbersCheck.h"
 #include "MakeMemberFunctionConstCheck.h"
+#include "MathMissingParenthesesCheck.h"
 #include "MisleadingIndentationCheck.h"
 #include "MisplacedArrayIndexCheck.h"
 #include "NamedParameterCheck.h"
@@ -101,6 +102,8 @@ class ReadabilityModule : public ClangTidyModule {
         "readability-identifier-naming");
     CheckFactories.registerCheck<ImplicitBoolConversionCheck>(
         "readability-implicit-bool-conversion");
+    CheckFactories.registerCheck<MathMissingParenthesesCheck>(
+        "readability-math-missing-parentheses");
     CheckFactories.registerCheck<RedundantInlineSpecifierCheck>(
         "readability-redundant-inline-specifier");
     CheckFactories.registerCheck<InconsistentDeclarationParameterNameCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index fd2cba4e4f463b..61b9665ffe73ed 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -100,6 +100,12 @@ Improvements to clang-tidy
 New checks
 ^^^^^^^^^^
 
+- New :doc:`readability-math-missing-parentheses
+  <clang-tidy/checks/readability/math-missing-parentheses>` check.
+
+  Checks for mathematical expressions that involve operators
+  of different priorities.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index f773e80b562e4f..0cc5c217899d4d 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -359,6 +359,7 @@ Clang-Tidy Checks
    :doc:`readability-isolate-declaration <readability/isolate-declaration>`, "Yes"
    :doc:`readability-magic-numbers <readability/magic-numbers>`,
    :doc:`readability-make-member-function-const <readability/make-member-function-const>`, "Yes"
+   :doc:`readability-math-missing-parentheses <readability/math-missing-parentheses>`, "Yes"
    :doc:`readability-misleading-indentation <readability/misleading-indentation>`,
    :doc:`readability-misplaced-array-index <readability/misplaced-array-index>`, "Yes"
    :doc:`readability-named-parameter <readability/named-parameter>`, "Yes"
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
new file mode 100644
index 00000000000000..fb3167e8e0f8f1
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -0,0 +1,19 @@
+.. title:: clang-tidy - readability-math-missing-parentheses
+
+readability-math-missing-parentheses
+====================================
+
+Checks for mathematical expressions that involve operators of different priorities.
+
+Before:
+
+.. code-block:: c++
+
+  int x = 1 + 2 * 3 - 4 / 5;
+
+
+After:
+
+.. code-block:: c++
+
+  int x = (1 + (2 * 3)) - (4 / 5);
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
new file mode 100644
index 00000000000000..54cc0d4dabbdee
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s readability-math-missing-parentheses %t
+
+// FIXME: Add something that triggers the check here.
+void f(){
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-FIXES: int a = 1 + (2 * 3);
+    int a = 1 + 2 * 3; 
+
+    int b = 1 + 2 + 3; // No warning
+
+    int c = 1 * 2 * 3; // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-FIXES: int d = (1 + (2 * 3)) - (4 / 5);
+    int d = 1 + 2 * 3 - 4 / 5;
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-FIXES: int e = (1 & (2 + 3)) | (4 * 5);
+    int e = 1 & 2 + 3 | 4 * 5;
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-FIXES: int f = (1 * -2) + 4;
+    int f = 1 * -2 + 4;
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-FIXES: int g = (((1 * 2) * 3) + 4) + 5;
+    int g = 1 * 2 * 3 + 4 + 5;
+
+    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    // CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
+    int h = 120 & 2 + 3 | 22 * 5;
+
+    int i = 1 & 2 & 3; // No warning
+
+    int j = 1 | 2 | 3; // No warning
+
+    int k = 1 ^ 2 ^ 3; // No warning
+
+    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    // CHECK-FIXES: int l = (1 + 2) ^ 3;
+    int l = 1 + 2 ^ 3;
+}

>From dcf739e077a393e71478a4ebe03eddb2a5f32f3c Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 11 Mar 2024 16:12:14 +0530
Subject: [PATCH 02/11] use ast,remove manual parsing

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../MathMissingParenthesesCheck.cpp           | 159 ++++--------------
 clang-tools-extra/docs/ReleaseNotes.rst       |   2 +-
 .../readability/math-missing-parentheses.cpp  |  48 +++++-
 3 files changed, 71 insertions(+), 138 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index d9574a9fb7a476..a3fad0a39bfbd5 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -11,8 +11,9 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Lex/Preprocessor.h"
-#include <set>
-#include <stack>
+#include "clang/Rewrite/Core/Rewriter.h"
+#include <iostream>
+using namespace std;
 
 using namespace clang::ast_matchers;
 
@@ -24,124 +25,25 @@ void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
                          .bind("binOp"),
                      this);
 }
-static int precedenceCheck(const char op) {
-  if (op == '/' || op == '*' || op == '%')
-    return 5;
 
-  else if (op == '+' || op == '-')
-    return 4;
-
-  else if (op == '&')
-    return 3;
-  else if (op == '^')
-    return 2;
-
-  else if (op == '|')
-    return 1;
-
-  else
-    return 0;
-}
-static bool isOperand(const char c) {
-  if (c >= 'a' && c <= 'z')
-    return true;
-  else if (c >= 'A' && c <= 'Z')
-    return true;
-  else if (c >= '0' && c <= '9')
-    return true;
-  else if (c == '$')
-    return true;
-  else
-    return false;
-}
-static bool conditionForNegative(const std::string s, int i,
-                                 const std::string CurStr) {
-  if (CurStr[0] == '-') {
-    if (i == 0) {
-      return true;
-    } else {
-      while (s[i - 1] == ' ') {
-        i--;
-      }
-      if (!isOperand(s[i - 1])) {
-        return true;
-      } else {
-        return false;
-      }
-    }
-  } else {
-    return false;
-  }
-}
-static std::string getOperationOrder(std::string s, std::set<char> &Operators) {
-  std::stack<std::string> StackOne;
-  std::string TempStr = "";
-  for (int i = 0; i < s.length(); i++) {
-    std::string CurStr = "";
-    CurStr += s[i];
-    if (CurStr == " ")
-      continue;
-    else {
-      if (isOperand(CurStr[0]) || conditionForNegative(s, i, CurStr)) {
-        while (i < s.length() && (isOperand(s[i]) || s[i] == '-')) {
-          if (s[i] == '-') {
-            TempStr += "$";
-          } else {
-            TempStr += CurStr;
-          }
-          i++;
-          CurStr = s[i];
-        }
-        TempStr += " ";
-      } else if (CurStr == "(") {
-        StackOne.push("(");
-      } else if (CurStr == ")") {
-        while (StackOne.top() != "(") {
-          TempStr += StackOne.top();
-          StackOne.pop();
-        }
-        StackOne.pop();
-      } else {
-        while (!StackOne.empty() && precedenceCheck(CurStr[0]) <=
-                                        precedenceCheck((StackOne.top())[0])) {
-          TempStr += StackOne.top();
-          StackOne.pop();
-        }
-        StackOne.push(CurStr);
-      }
-    }
-  }
-  while (!StackOne.empty()) {
-    TempStr += StackOne.top();
-    StackOne.pop();
-  }
-  std::stack<std::string> StackTwo;
-  for (int i = 0; i < TempStr.length(); i++) {
-    if (TempStr[i] == ' ')
-      continue;
-    else if (isOperand(TempStr[i])) {
-      std::string CurStr = "";
-      while (i < TempStr.length() && isOperand(TempStr[i])) {
-        if (TempStr[i] == '$') {
-          CurStr += "-";
-        } else {
-          CurStr += TempStr[i];
-        }
-        i++;
-      }
-      StackTwo.push(CurStr);
-    } else {
-      std::string OperandOne = StackTwo.top();
-      StackTwo.pop();
-      std::string OperandTwo = StackTwo.top();
-      StackTwo.pop();
-      Operators.insert(TempStr[i]);
-      StackTwo.push("(" + OperandTwo + " " + TempStr[i] + " " + OperandOne +
-                    ")");
-    }
+void addParantheses(const BinaryOperator *BinOp, clang::Rewriter &Rewrite,
+                    const BinaryOperator *ParentBinOp, bool &NeedToDiagnose) {
+  if (!BinOp)
+    return;
+  if (ParentBinOp != nullptr &&
+      ParentBinOp->getOpcode() != BinOp->getOpcode()) {
+    NeedToDiagnose = true;
   }
-  return StackTwo.top();
+  clang::SourceLocation StartLoc = BinOp->getLHS()->getBeginLoc();
+  clang::SourceLocation EndLoc = BinOp->getRHS()->getEndLoc();
+  Rewrite.InsertText(StartLoc, "(");
+  Rewrite.InsertTextAfterToken(EndLoc, ")");
+  addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()), Rewrite, BinOp,
+                 NeedToDiagnose);
+  addParantheses(dyn_cast<BinaryOperator>(BinOp->getRHS()), Rewrite, BinOp,
+                 NeedToDiagnose);
 }
+
 void MathMissingParenthesesCheck::check(
     const MatchFinder::MatchResult &Result) {
   const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
@@ -149,18 +51,17 @@ void MathMissingParenthesesCheck::check(
     return;
   clang::SourceManager &SM = *Result.SourceManager;
   clang::LangOptions LO = Result.Context->getLangOpts();
-  clang::CharSourceRange Range =
-      clang::CharSourceRange::getTokenRange(BinOp->getSourceRange());
-  std::string Expression = clang::Lexer::getSourceText(Range, SM, LO).str();
-  std::set<char> Operators;
-  std::string FinalExpression = getOperationOrder(Expression, Operators);
-  if (Operators.size() > 1) {
-    if (FinalExpression.length() > 2) {
-      FinalExpression = FinalExpression.substr(1, FinalExpression.length() - 2);
-    }
-    diag(BinOp->getBeginLoc(),
-         "add parantheses to clarify the precedence of operations")
-        << FixItHint::CreateReplacement(Range, FinalExpression);
+  Rewriter Rewrite(SM, LO);
+  bool NeedToDiagnose = false;
+  addParantheses(BinOp, Rewrite, nullptr, NeedToDiagnose);
+  clang::SourceLocation StartLoc = BinOp->getLHS()->getBeginLoc();
+  clang::SourceLocation EndLoc =
+      BinOp->getRHS()->getEndLoc().getLocWithOffset(1);
+  clang::SourceRange range(StartLoc, EndLoc);
+  std::string NewExpression = Rewrite.getRewrittenText(range);
+  if (NeedToDiagnose) {
+    diag(StartLoc, "add parantheses to clarify the precedence of operations")
+        << FixItHint::CreateReplacement(range, NewExpression);
   }
 }
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 61b9665ffe73ed..85fea576187f70 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -103,7 +103,7 @@ New checks
 - New :doc:`readability-math-missing-parentheses
   <clang-tidy/checks/readability/math-missing-parentheses>` check.
 
-  Checks for mathematical expressions that involve operators
+  Check for mising parantheses in mathematical expressions that involve operators
   of different priorities.
 
 New check aliases
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
index 54cc0d4dabbdee..ba936479b666c0 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -1,9 +1,28 @@
 // RUN: %check_clang_tidy %s readability-math-missing-parentheses %t
 
 // FIXME: Add something that triggers the check here.
+
+int foo(){
+    return 5;
+}
+
+int bar(){
+    return 4;
+}
+
+class fun{
+public:  
+    int A;
+    double B;
+    fun(){
+        A = 5;
+        B = 5.4;
+    }
+};
+
 void f(){
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int a = 1 + (2 * 3);
+    //CHECK-FIXES: int a = (1 + (2 * 3));
     int a = 1 + 2 * 3; 
 
     int b = 1 + 2 + 3; // No warning
@@ -11,23 +30,23 @@ void f(){
     int c = 1 * 2 * 3; // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int d = (1 + (2 * 3)) - (4 / 5);
+    //CHECK-FIXES: int d = ((1 + (2 * 3)) - (4 / 5));
     int d = 1 + 2 * 3 - 4 / 5;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int e = (1 & (2 + 3)) | (4 * 5);
+    //CHECK-FIXES: int e = ((1 & (2 + 3)) | (4 * 5));
     int e = 1 & 2 + 3 | 4 * 5;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int f = (1 * -2) + 4;
+    //CHECK-FIXES: int f = ((1 * -2) + 4);
     int f = 1 * -2 + 4;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int g = (((1 * 2) * 3) + 4) + 5;
+    //CHECK-FIXES: int g = ((((1 * 2) * 3) + 4) + 5);
     int g = 1 * 2 * 3 + 4 + 5;
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
+    // CHECK-FIXES: int h = ((120 & (2 + 3)) | (22 * 5));
     int h = 120 & 2 + 3 | 22 * 5;
 
     int i = 1 & 2 & 3; // No warning
@@ -37,6 +56,19 @@ void f(){
     int k = 1 ^ 2 ^ 3; // No warning
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int l = (1 + 2) ^ 3;
+    // CHECK-FIXES: int l = ((1 + 2) ^ 3);
     int l = 1 + 2 ^ 3;
-}
+
+    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    // CHECK-FIXES: int m = ((2 * foo()) + bar());
+    int m = 2 * foo() + bar();
+
+    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    // CHECK-FIXES: int n = ((1.05 * foo()) + double(bar()));
+    int n = 1.05 * foo() + double(bar());
+
+    // CHECK-MESSAGES: :[[@LINE+3]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    // CHECK-FIXES: int o = (1 + (obj.A * 3)) + obj.B;
+    fun obj;
+    int o = 1 + obj.A * 3 + obj.B; 
+}
\ No newline at end of file

>From de33e97d21ad1d7298b4f34a7659b0a569ce9799 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 15 Mar 2024 15:55:27 +0530
Subject: [PATCH 03/11] add ignoreimpcasts, use const variables, use
 createinsertion instead of createreplacement

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../MathMissingParenthesesCheck.cpp           | 55 ++++++++++---------
 .../readability/math-missing-parentheses.rst  |  3 +-
 .../readability/math-missing-parentheses.cpp  | 26 +++++----
 3 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index a3fad0a39bfbd5..ca1c6581fc60ee 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -7,13 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "MathMissingParenthesesCheck.h"
-#include "../utils/ASTUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Preprocessor.h"
 #include "clang/Rewrite/Core/Rewriter.h"
-#include <iostream>
-using namespace std;
 
 using namespace clang::ast_matchers;
 
@@ -26,42 +22,47 @@ void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
                      this);
 }
 
-void addParantheses(const BinaryOperator *BinOp, clang::Rewriter &Rewrite,
-                    const BinaryOperator *ParentBinOp, bool &NeedToDiagnose) {
+void addParantheses(
+    const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+    bool &NeedToDiagnose,
+    std::vector<std::pair<clang::SourceLocation, clang::SourceLocation>>
+        &Insertions) {
   if (!BinOp)
     return;
+
   if (ParentBinOp != nullptr &&
       ParentBinOp->getOpcode() != BinOp->getOpcode()) {
     NeedToDiagnose = true;
   }
-  clang::SourceLocation StartLoc = BinOp->getLHS()->getBeginLoc();
-  clang::SourceLocation EndLoc = BinOp->getRHS()->getEndLoc();
-  Rewrite.InsertText(StartLoc, "(");
-  Rewrite.InsertTextAfterToken(EndLoc, ")");
-  addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()), Rewrite, BinOp,
-                 NeedToDiagnose);
-  addParantheses(dyn_cast<BinaryOperator>(BinOp->getRHS()), Rewrite, BinOp,
-                 NeedToDiagnose);
+  clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+  clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
+  Insertions.push_back({StartLoc, EndLoc});
+  addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()),
+                 BinOp, NeedToDiagnose, Insertions);
+  addParantheses(dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()),
+                 BinOp, NeedToDiagnose, Insertions);
 }
 
 void MathMissingParenthesesCheck::check(
     const MatchFinder::MatchResult &Result) {
   const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
-  if (!BinOp)
-    return;
-  clang::SourceManager &SM = *Result.SourceManager;
-  clang::LangOptions LO = Result.Context->getLangOpts();
-  Rewriter Rewrite(SM, LO);
   bool NeedToDiagnose = false;
-  addParantheses(BinOp, Rewrite, nullptr, NeedToDiagnose);
-  clang::SourceLocation StartLoc = BinOp->getLHS()->getBeginLoc();
-  clang::SourceLocation EndLoc =
-      BinOp->getRHS()->getEndLoc().getLocWithOffset(1);
-  clang::SourceRange range(StartLoc, EndLoc);
-  std::string NewExpression = Rewrite.getRewrittenText(range);
+  std::vector<std::pair<clang::SourceLocation, clang::SourceLocation>>
+      Insertions;
+  addParantheses(BinOp, nullptr, NeedToDiagnose, Insertions);
+  const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+  const clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
+  const clang::SourceRange range(StartLoc, EndLoc);
+  if (!Insertions.empty()) {
+    Insertions.erase(Insertions.begin());
+  }
   if (NeedToDiagnose) {
-    diag(StartLoc, "add parantheses to clarify the precedence of operations")
-        << FixItHint::CreateReplacement(range, NewExpression);
+    auto const &Diag = diag(
+        StartLoc, "add parantheses to clarify the precedence of operations");
+    for (const auto &Insertion : Insertions) {
+      Diag << FixItHint::CreateInsertion(Insertion.first, "(");
+      Diag << FixItHint::CreateInsertion(Insertion.second, ")");
+    }
   }
 }
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
index fb3167e8e0f8f1..72bfdfb9e7242a 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -3,7 +3,8 @@
 readability-math-missing-parentheses
 ====================================
 
-Checks for mathematical expressions that involve operators of different priorities.
+Check for mising parantheses in mathematical expressions that involve operators
+of different priorities.
 
 Before:
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
index ba936479b666c0..a44d08f7b22c1d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -1,7 +1,5 @@
 // RUN: %check_clang_tidy %s readability-math-missing-parentheses %t
 
-// FIXME: Add something that triggers the check here.
-
 int foo(){
     return 5;
 }
@@ -22,7 +20,7 @@ class fun{
 
 void f(){
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int a = (1 + (2 * 3));
+    //CHECK-FIXES: int a = 1 + (2 * 3);
     int a = 1 + 2 * 3; 
 
     int b = 1 + 2 + 3; // No warning
@@ -30,23 +28,23 @@ void f(){
     int c = 1 * 2 * 3; // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int d = ((1 + (2 * 3)) - (4 / 5));
+    //CHECK-FIXES: int d = (1 + (2 * 3)) - (4 / 5);
     int d = 1 + 2 * 3 - 4 / 5;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int e = ((1 & (2 + 3)) | (4 * 5));
+    //CHECK-FIXES: int e = (1 & (2 + 3)) | (4 * 5);
     int e = 1 & 2 + 3 | 4 * 5;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int f = ((1 * -2) + 4);
+    //CHECK-FIXES: int f = (1 * -2) + 4;
     int f = 1 * -2 + 4;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int g = ((((1 * 2) * 3) + 4) + 5);
+    //CHECK-FIXES: int g = (((1 * 2) * 3) + 4) + 5;
     int g = 1 * 2 * 3 + 4 + 5;
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int h = ((120 & (2 + 3)) | (22 * 5));
+    // CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
     int h = 120 & 2 + 3 | 22 * 5;
 
     int i = 1 & 2 & 3; // No warning
@@ -56,19 +54,23 @@ void f(){
     int k = 1 ^ 2 ^ 3; // No warning
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int l = ((1 + 2) ^ 3);
+    // CHECK-FIXES: int l = (1 + 2) ^ 3;
     int l = 1 + 2 ^ 3;
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int m = ((2 * foo()) + bar());
+    // CHECK-FIXES: int m = (2 * foo()) + bar();
     int m = 2 * foo() + bar();
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int n = ((1.05 * foo()) + double(bar()));
+    // CHECK-FIXES: int n = (1.05 * foo()) + double(bar());
     int n = 1.05 * foo() + double(bar());
 
     // CHECK-MESSAGES: :[[@LINE+3]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int o = (1 + (obj.A * 3)) + obj.B;
     fun obj;
     int o = 1 + obj.A * 3 + obj.B; 
-}
\ No newline at end of file
+
+    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    // CHECK-FIXES: int p = 1U + (2 * 3);
+    int p = 1U + 2 * 3;
+}

>From fa95ab7ad216b6498b579db55ff1594da3fe0aab Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 15 Mar 2024 15:56:36 +0530
Subject: [PATCH 04/11] remove unnecessary header

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../clang-tidy/readability/MathMissingParenthesesCheck.cpp   | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index ca1c6581fc60ee..ad1d0744f660b3 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -9,7 +9,6 @@
 #include "MathMissingParenthesesCheck.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Rewrite/Core/Rewriter.h"
 
 using namespace clang::ast_matchers;
 
@@ -34,8 +33,8 @@ void addParantheses(
       ParentBinOp->getOpcode() != BinOp->getOpcode()) {
     NeedToDiagnose = true;
   }
-  clang::SourceLocation StartLoc = BinOp->getBeginLoc();
-  clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
+  const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+  const clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
   Insertions.push_back({StartLoc, EndLoc});
   addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()),
                  BinOp, NeedToDiagnose, Insertions);

>From 112692ab763c0364f729f8fdd828e85df1a7995e Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 24 Mar 2024 16:02:10 +0530
Subject: [PATCH 05/11] major fix

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../MathMissingParenthesesCheck.cpp           | 69 ++++++++++++-------
 .../readability/MathMissingParenthesesCheck.h |  4 +-
 clang-tools-extra/docs/ReleaseNotes.rst       |  4 +-
 .../readability/math-missing-parentheses.rst  | 11 ++-
 .../readability/math-missing-parentheses.cpp  |  6 +-
 5 files changed, 59 insertions(+), 35 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index ad1d0744f660b3..4a3e58fe8d0ef6 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -21,46 +21,65 @@ void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
                      this);
 }
 
-void addParantheses(
-    const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
-    bool &NeedToDiagnose,
-    std::vector<std::pair<clang::SourceLocation, clang::SourceLocation>>
-        &Insertions) {
+static int getPrecedence(const BinaryOperator *BinOp) {
   if (!BinOp)
-    return;
+    return 0;
+  switch (BinOp->getOpcode()) {
+  case BO_Mul:
+  case BO_Div:
+  case BO_Rem:
+    return 5;
+  case BO_Add:
+  case BO_Sub:
+    return 4;
+  case BO_And:
+    return 3;
+  case BO_Xor:
+    return 2;
+  case BO_Or:
+    return 1;
+  default:
+    return 0;
+  }
+}
+static bool addParantheses(const BinaryOperator *BinOp,
+                           const BinaryOperator *ParentBinOp,
+                           std::vector<clang::SourceRange> &Insertions) {
+  bool NeedToDiagnose = false;
+  if (!BinOp)
+    return NeedToDiagnose;
 
   if (ParentBinOp != nullptr &&
-      ParentBinOp->getOpcode() != BinOp->getOpcode()) {
+      getPrecedence(BinOp) != getPrecedence(ParentBinOp)) {
     NeedToDiagnose = true;
+    const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+    const clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
+    Insertions.push_back(clang::SourceRange(StartLoc, EndLoc));
   }
-  const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
-  const clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
-  Insertions.push_back({StartLoc, EndLoc});
-  addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()),
-                 BinOp, NeedToDiagnose, Insertions);
-  addParantheses(dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()),
-                 BinOp, NeedToDiagnose, Insertions);
+
+  NeedToDiagnose |= addParantheses(
+      dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()), BinOp,
+      Insertions);
+  NeedToDiagnose |= addParantheses(
+      dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()), BinOp,
+      Insertions);
+  return NeedToDiagnose;
 }
 
 void MathMissingParenthesesCheck::check(
     const MatchFinder::MatchResult &Result) {
   const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
   bool NeedToDiagnose = false;
-  std::vector<std::pair<clang::SourceLocation, clang::SourceLocation>>
-      Insertions;
-  addParantheses(BinOp, nullptr, NeedToDiagnose, Insertions);
+  std::vector<clang::SourceRange> Insertions;
   const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
-  const clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
-  const clang::SourceRange range(StartLoc, EndLoc);
-  if (!Insertions.empty()) {
-    Insertions.erase(Insertions.begin());
-  }
-  if (NeedToDiagnose) {
+
+  if (addParantheses(BinOp, nullptr, Insertions)) {
     auto const &Diag = diag(
         StartLoc, "add parantheses to clarify the precedence of operations");
     for (const auto &Insertion : Insertions) {
-      Diag << FixItHint::CreateInsertion(Insertion.first, "(");
-      Diag << FixItHint::CreateInsertion(Insertion.second, ")");
+      Diag << FixItHint::CreateInsertion(Insertion.getBegin(), "(");
+      Diag << FixItHint::CreateInsertion(Insertion.getEnd(), ")");
+      Diag << SourceRange(Insertion.getBegin(), Insertion.getEnd());
     }
   }
 }
diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
index 60b402831b45e0..0c46d683b2bfc7 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
@@ -13,8 +13,8 @@
 
 namespace clang::tidy::readability {
 
-/// Checks for mathematical expressions that involve operators of different
-/// priorities.
+/// Check for mising parantheses in mathematical expressions that involve
+/// operators of different priorities.
 ///
 /// For the user-facing documentation see:
 /// http://clang.llvm.org/extra/clang-tidy/checks/readability/math-missing-parentheses.html
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 85fea576187f70..008e5718bff577 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -103,8 +103,8 @@ New checks
 - New :doc:`readability-math-missing-parentheses
   <clang-tidy/checks/readability/math-missing-parentheses>` check.
 
-  Check for mising parantheses in mathematical expressions that involve operators
-  of different priorities.
+  Check for missing parentheses in mathematical expressions that involve
+  operators of different priorities.
 
 New check aliases
 ^^^^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
index 72bfdfb9e7242a..538ddf35b90c0a 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -3,8 +3,13 @@
 readability-math-missing-parentheses
 ====================================
 
-Check for mising parantheses in mathematical expressions that involve operators
-of different priorities.
+Check for missing parentheses in mathematical expressions that involve operators
+of different priorities. Parentheses in mathematical expressions clarify the order
+of operations, especially with different-priority operators. Lengthy or multiline
+expressions can obscure this order, leading to coding errors. IDEs can aid clarity
+by highlighting parentheses. Explicitly using parentheses also clarify what the 
+developer had in mind when writing the expression. Ensuring their presence reduces
+ambiguity and errors, promoting clearer and more maintainable code.
 
 Before:
 
@@ -17,4 +22,4 @@ After:
 
 .. code-block:: c++
 
-  int x = (1 + (2 * 3)) - (4 / 5);
\ No newline at end of file
+  int x = 1 + (2 * 3) - (4 / 5);
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
index a44d08f7b22c1d..a9ab207ba600e1 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -28,7 +28,7 @@ void f(){
     int c = 1 * 2 * 3; // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int d = (1 + (2 * 3)) - (4 / 5);
+    //CHECK-FIXES: int d = 1 + (2 * 3) - (4 / 5);
     int d = 1 + 2 * 3 - 4 / 5;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
@@ -40,7 +40,7 @@ void f(){
     int f = 1 * -2 + 4;
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    //CHECK-FIXES: int g = (((1 * 2) * 3) + 4) + 5;
+    //CHECK-FIXES: int g = (1 * 2 * 3) + 4 + 5;
     int g = 1 * 2 * 3 + 4 + 5;
 
     // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
@@ -66,7 +66,7 @@ void f(){
     int n = 1.05 * foo() + double(bar());
 
     // CHECK-MESSAGES: :[[@LINE+3]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int o = (1 + (obj.A * 3)) + obj.B;
+    // CHECK-FIXES: int o = 1 + (obj.A * 3) + obj.B; 
     fun obj;
     int o = 1 + obj.A * 3 + obj.B; 
 

>From 399605b1d633971b8f08f656fa06424458a030c1 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 24 Mar 2024 16:11:50 +0530
Subject: [PATCH 06/11] empty commit

Signed-off-by: 11happy <soni5happy at gmail.com>

>From 562fc31a845ed4fa889ee43158200eb9d3ed28d6 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 26 Mar 2024 10:26:08 +0530
Subject: [PATCH 07/11] small fixes

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../clang-tidy/readability/MathMissingParenthesesCheck.cpp   | 5 ++---
 .../checks/readability/math-missing-parentheses.rst          | 4 ++--
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index 4a3e58fe8d0ef6..3a0b262ed775aa 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -69,17 +69,16 @@ static bool addParantheses(const BinaryOperator *BinOp,
 void MathMissingParenthesesCheck::check(
     const MatchFinder::MatchResult &Result) {
   const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
-  bool NeedToDiagnose = false;
   std::vector<clang::SourceRange> Insertions;
   const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
 
   if (addParantheses(BinOp, nullptr, Insertions)) {
-    auto const &Diag = diag(
+    const auto &Diag = diag(
         StartLoc, "add parantheses to clarify the precedence of operations");
     for (const auto &Insertion : Insertions) {
       Diag << FixItHint::CreateInsertion(Insertion.getBegin(), "(");
       Diag << FixItHint::CreateInsertion(Insertion.getEnd(), ")");
-      Diag << SourceRange(Insertion.getBegin(), Insertion.getEnd());
+      Diag << Insertion;
     }
   }
 }
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
index 538ddf35b90c0a..96c4d73266f04b 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -4,10 +4,10 @@ readability-math-missing-parentheses
 ====================================
 
 Check for missing parentheses in mathematical expressions that involve operators
-of different priorities. Parentheses in mathematical expressions clarify the order
+of different priorities. Parentheses in mathematical expressions clarifies the order
 of operations, especially with different-priority operators. Lengthy or multiline
 expressions can obscure this order, leading to coding errors. IDEs can aid clarity
-by highlighting parentheses. Explicitly using parentheses also clarify what the 
+by highlighting parentheses. Explicitly using parentheses also clarifies what the 
 developer had in mind when writing the expression. Ensuring their presence reduces
 ambiguity and errors, promoting clearer and more maintainable code.
 

>From 183d123c1d49d79dd311ac5e4ec7e1d5d0f18f42 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 26 Mar 2024 18:16:56 +0530
Subject: [PATCH 08/11] correct clarify

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../clang-tidy/checks/readability/math-missing-parentheses.rst  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
index 96c4d73266f04b..3d254b5a126e98 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -4,7 +4,7 @@ readability-math-missing-parentheses
 ====================================
 
 Check for missing parentheses in mathematical expressions that involve operators
-of different priorities. Parentheses in mathematical expressions clarifies the order
+of different priorities. Parentheses in mathematical expressions clarify the order
 of operations, especially with different-priority operators. Lengthy or multiline
 expressions can obscure this order, leading to coding errors. IDEs can aid clarity
 by highlighting parentheses. Explicitly using parentheses also clarifies what the 

>From 7e3f39c65cd4ab98db3005b31476c88c069073b7 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 29 Mar 2024 22:49:57 +0530
Subject: [PATCH 09/11] operator wise warning

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../MathMissingParenthesesCheck.cpp           | 54 ++++++++++++++-----
 .../readability/MathMissingParenthesesCheck.h |  3 ++
 .../readability/math-missing-parentheses.cpp  | 27 ++++++----
 3 files changed, 59 insertions(+), 25 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index 3a0b262ed775aa..9e4ccad47fd9e4 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -9,6 +9,7 @@
 #include "MathMissingParenthesesCheck.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
 
 using namespace clang::ast_matchers;
 
@@ -16,6 +17,8 @@ namespace clang::tidy::readability {
 
 void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),
+                                    unless(allOf(hasOperatorName("&&"),
+                                                 hasOperatorName("||"))),
                                     hasDescendant(binaryOperator()))
                          .bind("binOp"),
                      this);
@@ -42,9 +45,13 @@ static int getPrecedence(const BinaryOperator *BinOp) {
     return 0;
   }
 }
-static bool addParantheses(const BinaryOperator *BinOp,
-                           const BinaryOperator *ParentBinOp,
-                           std::vector<clang::SourceRange> &Insertions) {
+static bool addParantheses(
+    const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+    std::vector<
+        std::pair<clang::SourceRange, std::pair<const clang::BinaryOperator *,
+                                                const clang::BinaryOperator *>>>
+        &Insertions,
+    const clang::SourceManager &SM, const clang::LangOptions &LangOpts) {
   bool NeedToDiagnose = false;
   if (!BinOp)
     return NeedToDiagnose;
@@ -53,32 +60,51 @@ static bool addParantheses(const BinaryOperator *BinOp,
       getPrecedence(BinOp) != getPrecedence(ParentBinOp)) {
     NeedToDiagnose = true;
     const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
-    const clang::SourceLocation EndLoc = BinOp->getEndLoc().getLocWithOffset(1);
-    Insertions.push_back(clang::SourceRange(StartLoc, EndLoc));
+    clang::SourceLocation EndLoc =
+        clang::Lexer::getLocForEndOfToken(BinOp->getEndLoc(), 0, SM, LangOpts);
+    Insertions.push_back(
+        {clang::SourceRange(StartLoc, EndLoc), {BinOp, ParentBinOp}});
   }
 
   NeedToDiagnose |= addParantheses(
       dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()), BinOp,
-      Insertions);
+      Insertions, SM, LangOpts);
   NeedToDiagnose |= addParantheses(
       dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()), BinOp,
-      Insertions);
+      Insertions, SM, LangOpts);
   return NeedToDiagnose;
 }
 
 void MathMissingParenthesesCheck::check(
     const MatchFinder::MatchResult &Result) {
   const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binOp");
-  std::vector<clang::SourceRange> Insertions;
+  std::vector<
+      std::pair<clang::SourceRange, std::pair<const clang::BinaryOperator *,
+                                              const clang::BinaryOperator *>>>
+      Insertions;
   const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+  const SourceManager &SM = *Result.SourceManager;
+  const clang::LangOptions &LO = Result.Context->getLangOpts();
 
-  if (addParantheses(BinOp, nullptr, Insertions)) {
-    const auto &Diag = diag(
-        StartLoc, "add parantheses to clarify the precedence of operations");
+  if (addParantheses(BinOp, nullptr, Insertions, SM, LO)) {
     for (const auto &Insertion : Insertions) {
-      Diag << FixItHint::CreateInsertion(Insertion.getBegin(), "(");
-      Diag << FixItHint::CreateInsertion(Insertion.getEnd(), ")");
-      Diag << Insertion;
+      const clang::BinaryOperator *BinOp1 = Insertion.second.first;
+      const clang::BinaryOperator *BinOp2 = Insertion.second.second;
+
+      int Precedence1 = getPrecedence(BinOp1);
+      int Precedence2 = getPrecedence(BinOp2);
+
+      auto Diag = diag(Insertion.first.getBegin(),
+                       "'%0' has higher precedence than '%1'; add parentheses "
+                       "to make the precedence of operations explicit")
+                  << (Precedence1 > Precedence2 ? BinOp1->getOpcodeStr()
+                                                : BinOp2->getOpcodeStr())
+                  << (Precedence1 > Precedence2 ? BinOp2->getOpcodeStr()
+                                                : BinOp1->getOpcodeStr());
+
+      Diag << FixItHint::CreateInsertion(Insertion.first.getBegin(), "(");
+      Diag << FixItHint::CreateInsertion(Insertion.first.getEnd(), ")");
+      Diag << Insertion.first;
     }
   }
 }
diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
index 0c46d683b2bfc7..9a9d2b3cfaabae 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.h
@@ -24,6 +24,9 @@ class MathMissingParenthesesCheck : public ClangTidyCheck {
       : ClangTidyCheck(Name, Context) {}
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  std::optional<TraversalKind> getCheckTraversalKind() const override {
+    return TK_IgnoreUnlessSpelledInSource;
+  }
 };
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
index a9ab207ba600e1..96cbdf43921d4a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -19,7 +19,7 @@ class fun{
 };
 
 void f(){
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:17: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     //CHECK-FIXES: int a = 1 + (2 * 3);
     int a = 1 + 2 * 3; 
 
@@ -27,23 +27,28 @@ void f(){
 
     int c = 1 * 2 * 3; // No warning
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '/' has higher precedence than '-'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     //CHECK-FIXES: int d = 1 + (2 * 3) - (4 / 5);
     int d = 1 + 2 * 3 - 4 / 5;
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '+' has higher precedence than '&'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '*' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     //CHECK-FIXES: int e = (1 & (2 + 3)) | (4 * 5);
     int e = 1 & 2 + 3 | 4 * 5;
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     //CHECK-FIXES: int f = (1 * -2) + 4;
     int f = 1 * -2 + 4;
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     //CHECK-FIXES: int g = (1 * 2 * 3) + 4 + 5;
     int g = 1 * 2 * 3 + 4 + 5;
 
-    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:19: warning: '+' has higher precedence than '&'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:27: warning: '*' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     // CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
     int h = 120 & 2 + 3 | 22 * 5;
 
@@ -53,24 +58,24 @@ void f(){
 
     int k = 1 ^ 2 ^ 3; // No warning
 
-    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '+' has higher precedence than '^'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     // CHECK-FIXES: int l = (1 + 2) ^ 3;
     int l = 1 + 2 ^ 3;
 
-    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     // CHECK-FIXES: int m = (2 * foo()) + bar();
     int m = 2 * foo() + bar();
 
-    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     // CHECK-FIXES: int n = (1.05 * foo()) + double(bar());
     int n = 1.05 * foo() + double(bar());
 
-    // CHECK-MESSAGES: :[[@LINE+3]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     // CHECK-FIXES: int o = 1 + (obj.A * 3) + obj.B; 
     fun obj;
     int o = 1 + obj.A * 3 + obj.B; 
 
-    // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: add parantheses to clarify the precedence of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:18: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
     // CHECK-FIXES: int p = 1U + (2 * 3);
     int p = 1U + 2 * 3;
 }

>From c6acf02dcad1db8674d0460dc234e6c717438f00 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 1 Apr 2024 21:00:37 +0530
Subject: [PATCH 10/11] remove the vector storing locations

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../MathMissingParenthesesCheck.cpp           | 79 ++++++++-----------
 clang-tools-extra/docs/ReleaseNotes.rst       | 12 +--
 .../readability/math-missing-parentheses.rst  |  4 +-
 .../readability/math-missing-parentheses.cpp  | 54 +++++++++----
 4 files changed, 79 insertions(+), 70 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
index 9e4ccad47fd9e4..e990e6a8675d69 100644
--- a/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/MathMissingParenthesesCheck.cpp
@@ -17,8 +17,9 @@ namespace clang::tidy::readability {
 
 void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),
-                                    unless(allOf(hasOperatorName("&&"),
-                                                 hasOperatorName("||"))),
+                                    unless(isAssignmentOperator()),
+                                    unless(isComparisonOperator()),
+                                    unless(hasAnyOperatorName("&&", "||")),
                                     hasDescendant(binaryOperator()))
                          .bind("binOp"),
                      this);
@@ -45,34 +46,40 @@ static int getPrecedence(const BinaryOperator *BinOp) {
     return 0;
   }
 }
-static bool addParantheses(
-    const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
-    std::vector<
-        std::pair<clang::SourceRange, std::pair<const clang::BinaryOperator *,
-                                                const clang::BinaryOperator *>>>
-        &Insertions,
-    const clang::SourceManager &SM, const clang::LangOptions &LangOpts) {
-  bool NeedToDiagnose = false;
+static void addParantheses(const BinaryOperator *BinOp,
+                           const BinaryOperator *ParentBinOp,
+                           ClangTidyCheck *Check,
+                           const clang::SourceManager &SM,
+                           const clang::LangOptions &LangOpts) {
   if (!BinOp)
-    return NeedToDiagnose;
+    return;
 
-  if (ParentBinOp != nullptr &&
-      getPrecedence(BinOp) != getPrecedence(ParentBinOp)) {
-    NeedToDiagnose = true;
+  int Precedence1 = getPrecedence(BinOp);
+  int Precedence2 = getPrecedence(ParentBinOp);
+
+  if (ParentBinOp != nullptr && Precedence1 != Precedence2) {
     const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
-    clang::SourceLocation EndLoc =
+    const clang::SourceLocation EndLoc =
         clang::Lexer::getLocForEndOfToken(BinOp->getEndLoc(), 0, SM, LangOpts);
-    Insertions.push_back(
-        {clang::SourceRange(StartLoc, EndLoc), {BinOp, ParentBinOp}});
+
+    auto Diag =
+        Check->diag(StartLoc,
+                    "'%0' has higher precedence than '%1'; add parentheses to "
+                    "explicitly specify the order of operations")
+        << (Precedence1 > Precedence2 ? BinOp->getOpcodeStr()
+                                      : ParentBinOp->getOpcodeStr())
+        << (Precedence1 > Precedence2 ? ParentBinOp->getOpcodeStr()
+                                      : BinOp->getOpcodeStr());
+
+    Diag << FixItHint::CreateInsertion(StartLoc, "(");
+    Diag << FixItHint::CreateInsertion(EndLoc, ")");
+    Diag << SourceRange(StartLoc, EndLoc);
   }
 
-  NeedToDiagnose |= addParantheses(
-      dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()), BinOp,
-      Insertions, SM, LangOpts);
-  NeedToDiagnose |= addParantheses(
-      dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()), BinOp,
-      Insertions, SM, LangOpts);
-  return NeedToDiagnose;
+  addParantheses(dyn_cast<BinaryOperator>(BinOp->getLHS()->IgnoreImpCasts()),
+                 BinOp, Check, SM, LangOpts);
+  addParantheses(dyn_cast<BinaryOperator>(BinOp->getRHS()->IgnoreImpCasts()),
+                 BinOp, Check, SM, LangOpts);
 }
 
 void MathMissingParenthesesCheck::check(
@@ -82,31 +89,9 @@ void MathMissingParenthesesCheck::check(
       std::pair<clang::SourceRange, std::pair<const clang::BinaryOperator *,
                                               const clang::BinaryOperator *>>>
       Insertions;
-  const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
   const SourceManager &SM = *Result.SourceManager;
   const clang::LangOptions &LO = Result.Context->getLangOpts();
-
-  if (addParantheses(BinOp, nullptr, Insertions, SM, LO)) {
-    for (const auto &Insertion : Insertions) {
-      const clang::BinaryOperator *BinOp1 = Insertion.second.first;
-      const clang::BinaryOperator *BinOp2 = Insertion.second.second;
-
-      int Precedence1 = getPrecedence(BinOp1);
-      int Precedence2 = getPrecedence(BinOp2);
-
-      auto Diag = diag(Insertion.first.getBegin(),
-                       "'%0' has higher precedence than '%1'; add parentheses "
-                       "to make the precedence of operations explicit")
-                  << (Precedence1 > Precedence2 ? BinOp1->getOpcodeStr()
-                                                : BinOp2->getOpcodeStr())
-                  << (Precedence1 > Precedence2 ? BinOp2->getOpcodeStr()
-                                                : BinOp1->getOpcodeStr());
-
-      Diag << FixItHint::CreateInsertion(Insertion.first.getBegin(), "(");
-      Diag << FixItHint::CreateInsertion(Insertion.first.getEnd(), ")");
-      Diag << Insertion.first;
-    }
-  }
+  addParantheses(BinOp, nullptr, this, SM, LO);
 }
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index ff47241908821a..fd4b70bde77e9a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -123,18 +123,18 @@ New checks
   Finds initializer lists for aggregate types that could be
   written as designated initializers instead.
 
-- New :doc:`readability-use-std-min-max
-  <clang-tidy/checks/readability/use-std-min-max>` check.
-
-  Replaces certain conditional statements with equivalent calls to
-  ``std::min`` or ``std::max``.
-
 - New :doc:`readability-math-missing-parentheses
   <clang-tidy/checks/readability/math-missing-parentheses>` check.
 
   Check for missing parentheses in mathematical expressions that involve
   operators of different priorities.
 
+- New :doc:`readability-use-std-min-max
+  <clang-tidy/checks/readability/use-std-min-max>` check.
+
+  Replaces certain conditional statements with equivalent calls to
+  ``std::min`` or ``std::max``.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
index 3d254b5a126e98..21d66daab334c6 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/math-missing-parentheses.rst
@@ -4,7 +4,9 @@ readability-math-missing-parentheses
 ====================================
 
 Check for missing parentheses in mathematical expressions that involve operators
-of different priorities. Parentheses in mathematical expressions clarify the order
+of different priorities.
+
+Parentheses in mathematical expressions clarify the order
 of operations, especially with different-priority operators. Lengthy or multiline
 expressions can obscure this order, leading to coding errors. IDEs can aid clarity
 by highlighting parentheses. Explicitly using parentheses also clarifies what the 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
index 96cbdf43921d4a..4e22d4b210de6f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -19,63 +19,85 @@ class fun{
 };
 
 void f(){
-    //CHECK-MESSAGES: :[[@LINE+2]]:17: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-FIXES: int a = 1 + (2 * 3);
     int a = 1 + 2 * 3; 
 
+    int a_negative = 1 + (2 * 3); // No warning
+
     int b = 1 + 2 + 3; // No warning
 
     int c = 1 * 2 * 3; // No warning
 
-    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
-    //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '/' has higher precedence than '-'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '/' has higher precedence than '-'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-FIXES: int d = 1 + (2 * 3) - (4 / 5);
     int d = 1 + 2 * 3 - 4 / 5;
 
-    //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
-    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '+' has higher precedence than '&'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
-    //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '*' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int d_negative = 1 + (2 * 3) - (4 / 5); // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '+' has higher precedence than '&'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '*' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-FIXES: int e = (1 & (2 + 3)) | (4 * 5);
     int e = 1 & 2 + 3 | 4 * 5;
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int e_negative = (1 & (2 + 3)) | (4 * 5); // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-FIXES: int f = (1 * -2) + 4;
     int f = 1 * -2 + 4;
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int f_negative = (1 * -2) + 4; // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-FIXES: int g = (1 * 2 * 3) + 4 + 5;
     int g = 1 * 2 * 3 + 4 + 5;
 
-    //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
-    //CHECK-MESSAGES: :[[@LINE+3]]:19: warning: '+' has higher precedence than '&'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
-    //CHECK-MESSAGES: :[[@LINE+2]]:27: warning: '*' has higher precedence than '|'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int g_negative = (1 * 2 * 3) + 4 + 5; // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:19: warning: '+' has higher precedence than '&'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:27: warning: '*' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
     int h = 120 & 2 + 3 | 22 * 5;
 
+    int h_negative = (120 & (2 + 3)) | (22 * 5); // No warning
+
     int i = 1 & 2 & 3; // No warning
 
     int j = 1 | 2 | 3; // No warning
 
     int k = 1 ^ 2 ^ 3; // No warning
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '+' has higher precedence than '^'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '+' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int l = (1 + 2) ^ 3;
     int l = 1 + 2 ^ 3;
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int l_negative = (1 + 2) ^ 3; // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int m = (2 * foo()) + bar();
     int m = 2 * foo() + bar();
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int m_negative = (2 * foo()) + bar(); // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int n = (1.05 * foo()) + double(bar());
     int n = 1.05 * foo() + double(bar());
 
-    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int n_negative = (1.05 * foo()) + double(bar()); // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int o = 1 + (obj.A * 3) + obj.B; 
     fun obj;
     int o = 1 + obj.A * 3 + obj.B; 
 
-    //CHECK-MESSAGES: :[[@LINE+2]]:18: warning: '*' has higher precedence than '+'; add parentheses to make the precedence of operations explicit [readability-math-missing-parentheses]
+    int o_negative = 1 + (obj.A * 3) + obj.B; // No warning
+
+    //CHECK-MESSAGES: :[[@LINE+2]]:18: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     // CHECK-FIXES: int p = 1U + (2 * 3);
     int p = 1U + 2 * 3;
+
+    int p_negative = 1U + (2 * 3); // No warning
 }

>From 41818f516a27616a6c73ea321d10d20ebcc4c3a1 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 1 Apr 2024 21:12:39 +0530
Subject: [PATCH 11/11] add macro tests

Signed-off-by: 11happy <soni5happy at gmail.com>
---
 .../readability/math-missing-parentheses.cpp  | 29 +++++++++++++++----
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
index 4e22d4b210de6f..b34d15aade866d 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/math-missing-parentheses.cpp
@@ -1,5 +1,13 @@
 // RUN: %check_clang_tidy %s readability-math-missing-parentheses %t
 
+#define MACRO_AND &
+#define MACRO_ADD +
+#define MACRO_OR |
+#define MACRO_MULTIPLY *
+#define MACRO_XOR ^
+#define MACRO_SUBTRACT -
+#define MACRO_DIVIDE /
+
 int foo(){
     return 5;
 }
@@ -59,7 +67,7 @@ void f(){
     //CHECK-MESSAGES: :[[@LINE+4]]:13: warning: '&' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-MESSAGES: :[[@LINE+3]]:19: warning: '+' has higher precedence than '&'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
     //CHECK-MESSAGES: :[[@LINE+2]]:27: warning: '*' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
+    //CHECK-FIXES: int h = (120 & (2 + 3)) | (22 * 5);
     int h = 120 & 2 + 3 | 22 * 5;
 
     int h_negative = (120 & (2 + 3)) | (22 * 5); // No warning
@@ -71,33 +79,42 @@ void f(){
     int k = 1 ^ 2 ^ 3; // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '+' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int l = (1 + 2) ^ 3;
+    //CHECK-FIXES: int l = (1 + 2) ^ 3;
     int l = 1 + 2 ^ 3;
 
     int l_negative = (1 + 2) ^ 3; // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int m = (2 * foo()) + bar();
+    //CHECK-FIXES: int m = (2 * foo()) + bar();
     int m = 2 * foo() + bar();
 
     int m_negative = (2 * foo()) + bar(); // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:13: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int n = (1.05 * foo()) + double(bar());
+    //CHECK-FIXES: int n = (1.05 * foo()) + double(bar());
     int n = 1.05 * foo() + double(bar());
 
     int n_negative = (1.05 * foo()) + double(bar()); // No warning
 
     //CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int o = 1 + (obj.A * 3) + obj.B; 
+    //CHECK-FIXES: int o = 1 + (obj.A * 3) + obj.B; 
     fun obj;
     int o = 1 + obj.A * 3 + obj.B; 
 
     int o_negative = 1 + (obj.A * 3) + obj.B; // No warning
 
     //CHECK-MESSAGES: :[[@LINE+2]]:18: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
-    // CHECK-FIXES: int p = 1U + (2 * 3);
+    //CHECK-FIXES: int p = 1U + (2 * 3);
     int p = 1U + 2 * 3;
 
     int p_negative = 1U + (2 * 3); // No warning
+    
+    //CHECK-MESSAGES: :[[@LINE+7]]:13: warning: '+' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+6]]:25: warning: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+5]]:53: warning: '&' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+4]]:53: warning: '^' has higher precedence than '|'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+3]]:77: warning: '-' has higher precedence than '^'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-MESSAGES: :[[@LINE+2]]:94: warning: '/' has higher precedence than '-'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses]
+    //CHECK-FIXES: int q = (1 MACRO_ADD (2 MACRO_MULTIPLY 3)) MACRO_OR ((4 MACRO_AND 5) MACRO_XOR (6 MACRO_SUBTRACT (7 MACRO_DIVIDE 8)));
+    int q = 1 MACRO_ADD 2 MACRO_MULTIPLY 3 MACRO_OR 4 MACRO_AND 5 MACRO_XOR 6 MACRO_SUBTRACT 7 MACRO_DIVIDE 8; // No warning
 }



More information about the cfe-commits mailing list