https://github.com/11happy updated https://github.com/llvm/llvm-project/pull/84481
>From 8fdf6306085ed4cf0f77b7e718e374e9f65fedf9 Mon Sep 17 00:00:00 2001 From: 11happy <soni5ha...@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 <soni5ha...@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 <soni5ha...@gmail.com> Date: Mon, 11 Mar 2024 16:12:14 +0530 Subject: [PATCH 02/11] use ast,remove manual parsing Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@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 <soni5ha...@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 <soni5ha...@gmail.com> Date: Fri, 15 Mar 2024 15:56:36 +0530 Subject: [PATCH 04/11] remove unnecessary header Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@gmail.com> Date: Sun, 24 Mar 2024 16:02:10 +0530 Subject: [PATCH 05/11] major fix Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@gmail.com> Date: Sun, 24 Mar 2024 16:11:50 +0530 Subject: [PATCH 06/11] empty commit Signed-off-by: 11happy <soni5ha...@gmail.com> >From 562fc31a845ed4fa889ee43158200eb9d3ed28d6 Mon Sep 17 00:00:00 2001 From: 11happy <soni5ha...@gmail.com> Date: Tue, 26 Mar 2024 10:26:08 +0530 Subject: [PATCH 07/11] small fixes Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@gmail.com> Date: Tue, 26 Mar 2024 18:16:56 +0530 Subject: [PATCH 08/11] correct clarify Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@gmail.com> Date: Fri, 29 Mar 2024 22:49:57 +0530 Subject: [PATCH 09/11] operator wise warning Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@gmail.com> Date: Mon, 1 Apr 2024 21:00:37 +0530 Subject: [PATCH 10/11] remove the vector storing locations Signed-off-by: 11happy <soni5ha...@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 <soni5ha...@gmail.com> Date: Mon, 1 Apr 2024 21:12:39 +0530 Subject: [PATCH 11/11] add macro tests Signed-off-by: 11happy <soni5ha...@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 } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits