[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { + +// Skip spaces and tabs from both strings +while (LIdx < Left->size() && (LData[LIdx] == ' ' || LData[LIdx] == '\t')) { + LIdx += 1; +} +while (RIdx < Right->size() && + (RData[RIdx] == ' ' || RData[RIdx] == '\t')) { + RIdx += 1; +} + +// If all not tabs and spaces are the same then return true +if (LIdx >= Left->size() && RIdx >= Right->size()) + return true; + +// If any characters differs then return false +else if (LData[LIdx] != RData[RIdx]) + return false; + +// If current char is the same ==> continue search +else { + LIdx += 1; + RIdx += 1; +} + } + // Shortest string is processed: issue a verdict + return LIdx >= Left->size() && RIdx >= Right->size(); +} + +static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp, + const ASTContext *Context) { + + if (!BinOp) +return false; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + const SourceManager &SM = Context->getSourceManager(); + + const SourceRange Lsr = Lhs->getSourceRange(); + const SourceRange Rsr = Rhs->getSourceRange(); + if (Lsr.getBegin().isMacroID()) { earnol wrote: Checking expressions like +VALUE was not a goal of this function in the first place. But i agree the case like `if(+VALUE == +VALUE)` is redundant and should be properly detected. I'll add it to lit tests and make sure it will get detected. https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { earnol wrote: I see. StringRef drop_front is calling substr version (https://llvm.org/doxygen/SimplifyLibCalls_8cpp_source.html#l00356) not doing string duplication, so this approach should have the same the same efficiency. https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -1250,6 +1250,9 @@ Improvements - Improved the handling of the ``ownership_returns`` attribute. Now, Clang reports an error if the attribute is attached to a function that returns a non-pointer value. Fixes (#GH99501) +- Improved ``misc-redundant-expression`` checker potentially reducing number of false PiotrZSL wrote: Wrong file, remove this, you got already entry in other ReleaseNotes https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, PiotrZSL wrote: ptr to llvm::StringRef is a bad habit, pass it by value https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { + +// Skip spaces and tabs from both strings +while (LIdx < Left->size() && (LData[LIdx] == ' ' || LData[LIdx] == '\t')) { + LIdx += 1; +} +while (RIdx < Right->size() && + (RData[RIdx] == ' ' || RData[RIdx] == '\t')) { + RIdx += 1; +} + +// If all not tabs and spaces are the same then return true +if (LIdx >= Left->size() && RIdx >= Right->size()) + return true; + +// If any characters differs then return false +else if (LData[LIdx] != RData[RIdx]) + return false; + +// If current char is the same ==> continue search +else { + LIdx += 1; + RIdx += 1; +} + } + // Shortest string is processed: issue a verdict + return LIdx >= Left->size() && RIdx >= Right->size(); +} + +static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp, + const ASTContext *Context) { + + if (!BinOp) +return false; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + const SourceManager &SM = Context->getSourceManager(); + + const SourceRange Lsr = Lhs->getSourceRange(); + const SourceRange Rsr = Rhs->getSourceRange(); + if (Lsr.getBegin().isMacroID()) { +// Left is macro so right macro too +if (Rsr.getBegin().isMacroID()) { + // Both sides are macros so they are same macro or literal + const llvm::StringRef L = Lexer::getSourceText( + CharSourceRange::getTokenRange(Lsr), SM, LangOptions(), 0); + const llvm::StringRef R = Lexer::getSourceText( + CharSourceRange::getTokenRange(Rsr), SM, LangOptions(), 0); + return areStringsSameIgnoreSpaces(&L, &R); +} +// Left is macro but right is not so they are not same macro or literal +return false; + } else { +const auto *Lil = dyn_cast(Lhs); +const auto *Ril = dyn_cast(Rhs); +if (Lil && Ril) { PiotrZSL wrote: drop {} https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { + +// Skip spaces and tabs from both strings +while (LIdx < Left->size() && (LData[LIdx] == ' ' || LData[LIdx] == '\t')) { + LIdx += 1; +} +while (RIdx < Right->size() && + (RData[RIdx] == ' ' || RData[RIdx] == '\t')) { + RIdx += 1; +} + +// If all not tabs and spaces are the same then return true +if (LIdx >= Left->size() && RIdx >= Right->size()) + return true; + +// If any characters differs then return false +else if (LData[LIdx] != RData[RIdx]) + return false; + +// If current char is the same ==> continue search +else { + LIdx += 1; + RIdx += 1; +} + } + // Shortest string is processed: issue a verdict + return LIdx >= Left->size() && RIdx >= Right->size(); +} + +static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp, + const ASTContext *Context) { + + if (!BinOp) +return false; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + const SourceManager &SM = Context->getSourceManager(); + + const SourceRange Lsr = Lhs->getSourceRange(); + const SourceRange Rsr = Rhs->getSourceRange(); + if (Lsr.getBegin().isMacroID()) { +// Left is macro so right macro too +if (Rsr.getBegin().isMacroID()) { + // Both sides are macros so they are same macro or literal + const llvm::StringRef L = Lexer::getSourceText( + CharSourceRange::getTokenRange(Lsr), SM, LangOptions(), 0); + const llvm::StringRef R = Lexer::getSourceText( + CharSourceRange::getTokenRange(Rsr), SM, LangOptions(), 0); + return areStringsSameIgnoreSpaces(&L, &R); +} +// Left is macro but right is not so they are not same macro or literal +return false; + } else { PiotrZSL wrote: no need for else, previous if ends with return. https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { + +// Skip spaces and tabs from both strings +while (LIdx < Left->size() && (LData[LIdx] == ' ' || LData[LIdx] == '\t')) { + LIdx += 1; +} +while (RIdx < Right->size() && + (RData[RIdx] == ' ' || RData[RIdx] == '\t')) { + RIdx += 1; +} + +// If all not tabs and spaces are the same then return true +if (LIdx >= Left->size() && RIdx >= Right->size()) + return true; + +// If any characters differs then return false +else if (LData[LIdx] != RData[RIdx]) + return false; + +// If current char is the same ==> continue search +else { + LIdx += 1; + RIdx += 1; +} + } + // Shortest string is processed: issue a verdict + return LIdx >= Left->size() && RIdx >= Right->size(); +} + +static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp, + const ASTContext *Context) { + + if (!BinOp) +return false; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + const SourceManager &SM = Context->getSourceManager(); + + const SourceRange Lsr = Lhs->getSourceRange(); + const SourceRange Rsr = Rhs->getSourceRange(); + if (Lsr.getBegin().isMacroID()) { +// Left is macro so right macro too +if (Rsr.getBegin().isMacroID()) { + // Both sides are macros so they are same macro or literal + const llvm::StringRef L = Lexer::getSourceText( + CharSourceRange::getTokenRange(Lsr), SM, LangOptions(), 0); + const llvm::StringRef R = Lexer::getSourceText( + CharSourceRange::getTokenRange(Rsr), SM, LangOptions(), 0); PiotrZSL wrote: get proper LangOptions from ASTContext https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { + +// Skip spaces and tabs from both strings +while (LIdx < Left->size() && (LData[LIdx] == ' ' || LData[LIdx] == '\t')) { + LIdx += 1; +} +while (RIdx < Right->size() && + (RData[RIdx] == ' ' || RData[RIdx] == '\t')) { + RIdx += 1; +} + +// If all not tabs and spaces are the same then return true +if (LIdx >= Left->size() && RIdx >= Right->size()) + return true; + +// If any characters differs then return false +else if (LData[LIdx] != RData[RIdx]) + return false; + +// If current char is the same ==> continue search +else { + LIdx += 1; + RIdx += 1; +} + } + // Shortest string is processed: issue a verdict + return LIdx >= Left->size() && RIdx >= Right->size(); +} + +static bool areExprsSameMacroOrLiteral(const BinaryOperator *BinOp, + const ASTContext *Context) { + + if (!BinOp) +return false; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + const SourceManager &SM = Context->getSourceManager(); + + const SourceRange Lsr = Lhs->getSourceRange(); + const SourceRange Rsr = Rhs->getSourceRange(); + if (Lsr.getBegin().isMacroID()) { PiotrZSL wrote: problem with this is that you do not know if every part of LHS or RHS is an macro, because you checking only source of first token. If I would write: +VALUE, where #define VALUE 10, then it would fail. I think that there is some function in /utils/ that may help here https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { +return true; + } + // Do running index comparison + size_t LIdx = 0; + size_t RIdx = 0; + const char *LData = Left->data(); + const char *RData = Right->data(); + while (LIdx < Left->size() && RIdx < Right->size()) { PiotrZSL wrote: write this using ltrim and drop_front, we in 2025, no need to go back to legacy C++ ``` Left = Left.trim(); Right = Right.trim(); while(!Left.empty() && !Right.empty()) { Left = Left.ltrim(); Right = Right.ltrim(); if (Left.front() != Right.front()) return false; Left = Left.drop_front(); Right = Right.drop_front(); } return Left.empty() && Right.empty(); ``` https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const SourceLocation LhsLoc = LhsExpr->getExprLoc(); + const SourceLocation RhsLoc = RhsExpr->getExprLoc(); return LhsLoc.isMacroID() != RhsLoc.isMacroID(); } + +static bool areStringsSameIgnoreSpaces(const llvm::StringRef *Left, + const llvm::StringRef *Right) { + if (Left == Right) +return true; + if (Left->compare(*Right) == 0) { PiotrZSL wrote: no need for "{}", use operator == (it's a free standing function, that's why you may not see it in documentation) https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
earnol wrote: A gentle reminder to request a review for this PR since it is a week without a review. https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/122841 >From 9f658b50f70b1363d2daa26864f59934718384cc Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Mon, 13 Jan 2025 20:19:58 -0500 Subject: [PATCH] [clang-tidy] Address false positives in misc-redundant-expression checker Address situations when misc-redundant-expression checker provides excessive diagnostics for situations with different macros having the same value. In perticular situations described in the initial report of https://github.com/llvm/llvm-project/issues/118885 are addressed. The situations which are popped inside discussion like if (A + B == B + A) for macros are not properly addressed by this patch. But I still believe even in the current state the patch can be useful. --- .../misc/RedundantExpressionCheck.cpp | 166 --- clang-tools-extra/docs/ReleaseNotes.rst | 2 +- .../checks/misc/redundant-expression.rst | 14 +- .../checkers/misc/redundant-expression.cpp| 193 ++ clang/docs/ReleaseNotes.rst | 3 + 5 files changed, 347 insertions(+), 31 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index fc35bc22c52e04..31650309ecf8b3 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { return cast(Left)->getOpcode() == cast(Right)->getOpcode(); case Stmt::UnaryExprOrTypeTraitExprClass: -const auto *LeftUnaryExpr = -cast(Left); -const auto *RightUnaryExpr = -cast(Right); +const auto *LeftUnaryExpr = cast(Left); +const auto *RightUnaryExpr = cast(Right); if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType()) return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() && LeftUnaryExpr->getArgumentType() == @@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr( Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0); OperandExpr = OverloadedOperatorExpr; -Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator()); +Opcode = BinaryOperator::getOverloadedOpcode( +OverloadedOperatorExpr->getOperator()); if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr)) return false; @@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr( } // Checks for expressions like (X == 4) && (Y != 9) -static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) { +static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, + const ASTContext *AstCtx) { const auto *LhsBinOp = dyn_cast(BinOp->getLHS()); const auto *RhsBinOp = dyn_cast(BinOp->getRHS()); @@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A return false; } +static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant( +const BinaryOperator *&BinOp, const ASTContext *AstCtx) { + if (areSidesBinaryConstExpressions(BinOp, AstCtx)) +return true; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + + if (!Lhs || !Rhs) +return false; + + auto IsDefineExpr = [AstCtx](const Expr *E) { +const SourceRange Lsr = E->getSourceRange(); +if (!Lsr.getBegin().isMacroID() || E->isValueDependent() || +!E->isIntegerConstantExpr(*AstCtx)) + return false; +return true; + }; + + return IsDefineExpr(Lhs) || IsDefineExpr(Rhs); +} + // Retrieves integer constant subexpressions from binary operator expressions // that have two equivalent sides. // E.g.: from (X == 5) && (X == 5) retrieves 5 and 5. @@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp, } static bool isSameRawIdentifierToken(const Token &T1, const Token &T2, -const SourceManager &SM) { + const SourceManager &SM) { if (T1.getKind() != T2.getKind()) return false; if (T1.isNot(tok::raw_identifier)) @@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr, const ASTContext *AstCtx) { if (!LhsExpr || !RhsExpr) return false; - SourceRange Lsr = LhsExpr->getSourceRange(); - SourceRange Rsr = RhsExpr->getSourceRange(); + const SourceRange Lsr = LhsExpr->getSourceRange(); + const SourceRange Rsr = RhsExpr->getSourceRange(); if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID()) return false; @@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; -
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/122841 >From 1e0f301f1c41e7f678c3eac2a067a7c81caa3228 Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Mon, 13 Jan 2025 20:19:58 -0500 Subject: [PATCH] [clang-tidy] Address false positives in misc-redundant-expression checker Address situations when misc-redundant-expression checker provides excessive diagnostics for situations with different macros having the same value. In perticular situations described in the initial report of https://github.com/llvm/llvm-project/issues/118885 are addressed. The situations which are popped inside discussion like if (A + B == B + A) for macros are not properly addressed by this patch. But I still believe even in the current state the patch can be useful. --- .../misc/RedundantExpressionCheck.cpp | 166 --- clang-tools-extra/docs/ReleaseNotes.rst | 2 +- .../checkers/misc/redundant-expression.cpp| 193 ++ clang/docs/ReleaseNotes.rst | 3 + 4 files changed, 339 insertions(+), 25 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index fc35bc22c52e04..31650309ecf8b3 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { return cast(Left)->getOpcode() == cast(Right)->getOpcode(); case Stmt::UnaryExprOrTypeTraitExprClass: -const auto *LeftUnaryExpr = -cast(Left); -const auto *RightUnaryExpr = -cast(Right); +const auto *LeftUnaryExpr = cast(Left); +const auto *RightUnaryExpr = cast(Right); if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType()) return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() && LeftUnaryExpr->getArgumentType() == @@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr( Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0); OperandExpr = OverloadedOperatorExpr; -Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator()); +Opcode = BinaryOperator::getOverloadedOpcode( +OverloadedOperatorExpr->getOperator()); if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr)) return false; @@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr( } // Checks for expressions like (X == 4) && (Y != 9) -static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) { +static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, + const ASTContext *AstCtx) { const auto *LhsBinOp = dyn_cast(BinOp->getLHS()); const auto *RhsBinOp = dyn_cast(BinOp->getRHS()); @@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A return false; } +static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant( +const BinaryOperator *&BinOp, const ASTContext *AstCtx) { + if (areSidesBinaryConstExpressions(BinOp, AstCtx)) +return true; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + + if (!Lhs || !Rhs) +return false; + + auto IsDefineExpr = [AstCtx](const Expr *E) { +const SourceRange Lsr = E->getSourceRange(); +if (!Lsr.getBegin().isMacroID() || E->isValueDependent() || +!E->isIntegerConstantExpr(*AstCtx)) + return false; +return true; + }; + + return IsDefineExpr(Lhs) || IsDefineExpr(Rhs); +} + // Retrieves integer constant subexpressions from binary operator expressions // that have two equivalent sides. // E.g.: from (X == 5) && (X == 5) retrieves 5 and 5. @@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp, } static bool isSameRawIdentifierToken(const Token &T1, const Token &T2, -const SourceManager &SM) { + const SourceManager &SM) { if (T1.getKind() != T2.getKind()) return false; if (T1.isNot(tok::raw_identifier)) @@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr, const ASTContext *AstCtx) { if (!LhsExpr || !RhsExpr) return false; - SourceRange Lsr = LhsExpr->getSourceRange(); - SourceRange Rsr = RhsExpr->getSourceRange(); + const SourceRange Lsr = LhsExpr->getSourceRange(); + const SourceRange Rsr = RhsExpr->getSourceRange(); if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID()) return false; @@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - Source
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/122841 >From 4d49ec7e0d0b1f3f38fa3c3df30dc38627d8997d Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Mon, 13 Jan 2025 20:19:58 -0500 Subject: [PATCH] [clang-tidy] Address false positives in misc-redundant-expression checker Address situations when misc-redundant-expression checker provides excessive diagnostics for situations with different macros having the same value. In perticular situations described in the initial report of https://github.com/llvm/llvm-project/issues/118885 are addressed. The situations which are popped inside discussion like if (A + B == B + A) for macros are not properly addressed by this patch. But I still believe even in the current state the patch can be useful. --- .../misc/RedundantExpressionCheck.cpp | 166 --- .../checkers/misc/redundant-expression.cpp| 193 ++ clang/docs/ReleaseNotes.rst | 3 + 3 files changed, 338 insertions(+), 24 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index fc35bc22c52e04..31650309ecf8b3 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { return cast(Left)->getOpcode() == cast(Right)->getOpcode(); case Stmt::UnaryExprOrTypeTraitExprClass: -const auto *LeftUnaryExpr = -cast(Left); -const auto *RightUnaryExpr = -cast(Right); +const auto *LeftUnaryExpr = cast(Left); +const auto *RightUnaryExpr = cast(Right); if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType()) return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() && LeftUnaryExpr->getArgumentType() == @@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr( Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0); OperandExpr = OverloadedOperatorExpr; -Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator()); +Opcode = BinaryOperator::getOverloadedOpcode( +OverloadedOperatorExpr->getOperator()); if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr)) return false; @@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr( } // Checks for expressions like (X == 4) && (Y != 9) -static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) { +static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, + const ASTContext *AstCtx) { const auto *LhsBinOp = dyn_cast(BinOp->getLHS()); const auto *RhsBinOp = dyn_cast(BinOp->getRHS()); @@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A return false; } +static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant( +const BinaryOperator *&BinOp, const ASTContext *AstCtx) { + if (areSidesBinaryConstExpressions(BinOp, AstCtx)) +return true; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + + if (!Lhs || !Rhs) +return false; + + auto IsDefineExpr = [AstCtx](const Expr *E) { +const SourceRange Lsr = E->getSourceRange(); +if (!Lsr.getBegin().isMacroID() || E->isValueDependent() || +!E->isIntegerConstantExpr(*AstCtx)) + return false; +return true; + }; + + return IsDefineExpr(Lhs) || IsDefineExpr(Rhs); +} + // Retrieves integer constant subexpressions from binary operator expressions // that have two equivalent sides. // E.g.: from (X == 5) && (X == 5) retrieves 5 and 5. @@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp, } static bool isSameRawIdentifierToken(const Token &T1, const Token &T2, -const SourceManager &SM) { + const SourceManager &SM) { if (T1.getKind() != T2.getKind()) return false; if (T1.isNot(tok::raw_identifier)) @@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr, const ASTContext *AstCtx) { if (!LhsExpr || !RhsExpr) return false; - SourceRange Lsr = LhsExpr->getSourceRange(); - SourceRange Rsr = RhsExpr->getSourceRange(); + const SourceRange Lsr = LhsExpr->getSourceRange(); + const SourceRange Rsr = RhsExpr->getSourceRange(); if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID()) return false; @@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - SourceLocation RhsLoc = RhsExpr->getExprLoc(); + const Source
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol updated https://github.com/llvm/llvm-project/pull/122841 >From abbc1142211abe99ae36ab0bde5803e375a2 Mon Sep 17 00:00:00 2001 From: Vladislav Aranov Date: Mon, 13 Jan 2025 20:19:58 -0500 Subject: [PATCH] [clang-tidy] Address false positives in misc-redundant-expression checker Address situations when misc-redundant-expression checker provides excessive diagnostics for situations with different macros having the same value. In perticular situations described in the initial report of https://github.com/llvm/llvm-project/issues/118885 are addressed. The situations which are popped inside discussion like if (A + B == B + A) for macros are not properly addressed by this patch. But I still believe even in the current state the patch can be useful. --- .../misc/RedundantExpressionCheck.cpp | 166 --- clang-tools-extra/docs/ReleaseNotes.rst | 2 +- .../checkers/misc/redundant-expression.cpp| 193 ++ clang/docs/ReleaseNotes.rst | 3 + 4 files changed, 339 insertions(+), 25 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index fc35bc22c52e04..31650309ecf8b3 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) { return cast(Left)->getOpcode() == cast(Right)->getOpcode(); case Stmt::UnaryExprOrTypeTraitExprClass: -const auto *LeftUnaryExpr = -cast(Left); -const auto *RightUnaryExpr = -cast(Right); +const auto *LeftUnaryExpr = cast(Left); +const auto *RightUnaryExpr = cast(Right); if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType()) return LeftUnaryExpr->getKind() == RightUnaryExpr->getKind() && LeftUnaryExpr->getArgumentType() == @@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr( Symbol = OverloadedOperatorExpr->getArg(IntegerConstantIsFirstArg ? 1 : 0); OperandExpr = OverloadedOperatorExpr; -Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator()); +Opcode = BinaryOperator::getOverloadedOpcode( +OverloadedOperatorExpr->getOperator()); if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr)) return false; @@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr( } // Checks for expressions like (X == 4) && (Y != 9) -static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) { +static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, + const ASTContext *AstCtx) { const auto *LhsBinOp = dyn_cast(BinOp->getLHS()); const auto *RhsBinOp = dyn_cast(BinOp->getRHS()); @@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A return false; } +static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant( +const BinaryOperator *&BinOp, const ASTContext *AstCtx) { + if (areSidesBinaryConstExpressions(BinOp, AstCtx)) +return true; + + const Expr *Lhs = BinOp->getLHS(); + const Expr *Rhs = BinOp->getRHS(); + + if (!Lhs || !Rhs) +return false; + + auto IsDefineExpr = [AstCtx](const Expr *E) { +const SourceRange Lsr = E->getSourceRange(); +if (!Lsr.getBegin().isMacroID() || E->isValueDependent() || +!E->isIntegerConstantExpr(*AstCtx)) + return false; +return true; + }; + + return IsDefineExpr(Lhs) || IsDefineExpr(Rhs); +} + // Retrieves integer constant subexpressions from binary operator expressions // that have two equivalent sides. // E.g.: from (X == 5) && (X == 5) retrieves 5 and 5. @@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp, } static bool isSameRawIdentifierToken(const Token &T1, const Token &T2, -const SourceManager &SM) { + const SourceManager &SM) { if (T1.getKind() != T2.getKind()) return false; if (T1.isNot(tok::raw_identifier)) @@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr, const ASTContext *AstCtx) { if (!LhsExpr || !RhsExpr) return false; - SourceRange Lsr = LhsExpr->getSourceRange(); - SourceRange Rsr = RhsExpr->getSourceRange(); + const SourceRange Lsr = LhsExpr->getSourceRange(); + const SourceRange Rsr = RhsExpr->getSourceRange(); if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID()) return false; @@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, if (!LhsExpr || !RhsExpr) return false; - SourceLocation LhsLoc = LhsExpr->getExprLoc(); - Source
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [clang-tidy] Address false positives in misc-redundant-expression checker (PR #122841)
https://github.com/earnol edited https://github.com/llvm/llvm-project/pull/122841 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits