[clang] [llvm] [clang-tools-extra] Add clang-tidy check to suggest replacement of conditional statement with std::min/std::max (PR #77816)
Bhuminjay Soni via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 1 02:15:18 PST 2024
https://github.com/11happy updated https://github.com/llvm/llvm-project/pull/77816
>From 1883d987b2f83adaef05fdb47ae25c7b06582a64 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 00:02:46 +0530
Subject: [PATCH 01/47] Add readability check to suggest replacement of
conditional statement with std::min/std::max
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/readability/CMakeLists.txt | 1 +
.../ConditionaltostdminmaxCheck.cpp | 86 +++++++++++++++++++
.../readability/ConditionaltostdminmaxCheck.h | 30 +++++++
.../readability/ReadabilityTidyModule.cpp | 3 +
clang-tools-extra/docs/ReleaseNotes.rst | 6 ++
.../docs/clang-tidy/checks/list.rst | 1 +
.../readability/ConditionalToStdMinMax.rst | 29 +++++++
.../readability/ConditionalToStdMinMax.cpp | 27 ++++++
8 files changed, 183 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 408c822b861c5..4bc373bb69bb8 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -8,6 +8,7 @@ add_clang_library(clangTidyReadabilityModule
AvoidReturnWithVoidValueCheck.cpp
AvoidUnconditionalPreprocessorIfCheck.cpp
BracesAroundStatementsCheck.cpp
+ ConditionaltostdminmaxCheck.cpp
ConstReturnTypeCheck.cpp
ContainerContainsCheck.cpp
ContainerDataPointerCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
new file mode 100644
index 0000000000000..fba8c68f73745
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
@@ -0,0 +1,86 @@
+//===--- ConditionaltostdminmaxCheck.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 "ConditionaltostdminmaxCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void ConditionaltostdminmaxCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ ifStmt(
+ has(
+ binaryOperator(
+ anyOf(hasOperatorName("<"),hasOperatorName(">")),
+ hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar1"))),
+ hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar1")))
+ )
+ )
+ ,
+ hasThen(
+ stmt(
+ binaryOperator(
+ hasOperatorName("="),
+ hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar2"))),
+ hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar2")))
+ )
+ )
+ )
+ ).bind("ifStmt"),this);
+
+
+
+}
+
+void ConditionaltostdminmaxCheck::check(const MatchFinder::MatchResult &Result) {
+ const DeclRefExpr *lhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar1");
+ const DeclRefExpr *rhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar1");
+ const DeclRefExpr *lhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar2");
+ const DeclRefExpr *rhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar2");
+ const IfStmt *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
+
+ if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
+ return;
+
+ const BinaryOperator *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
+ if (!binaryOp)
+ return;
+
+ SourceLocation ifLocation = ifStmt->getIfLoc();
+ SourceLocation thenLocation = ifStmt->getEndLoc();
+
+ if(binaryOp->getOpcode() == BO_LT){
+ if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::max instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ }
+ else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::min instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ }
+ }
+ else if(binaryOp->getOpcode() == BO_GT){
+ if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::min instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ }
+ else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::max instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ }
+ }
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
new file mode 100644
index 0000000000000..b7eabcc7d16d4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
@@ -0,0 +1,30 @@
+//===--- ConditionaltostdminmaxCheck.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_CONDITIONALTOSTDMINMAXCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONDITIONALTOSTDMINMAXCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+/// FIXME: replaces certain conditional statements with equivalent std::min or std::max expressions, improving readability and promoting the use of standard library functions."
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/ConditionalToStdMinMax.html
+class ConditionaltostdminmaxCheck : public ClangTidyCheck {
+public:
+ ConditionaltostdminmaxCheck(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_CONDITIONALTOSTDMINMAXCHECK_H
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 0b0aad7c0dcb3..63f8f03be6bb9 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -13,6 +13,7 @@
#include "AvoidReturnWithVoidValueCheck.h"
#include "AvoidUnconditionalPreprocessorIfCheck.h"
#include "BracesAroundStatementsCheck.h"
+#include "ConditionaltostdminmaxCheck.h"
#include "ConstReturnTypeCheck.h"
#include "ContainerContainsCheck.h"
#include "ContainerDataPointerCheck.h"
@@ -62,6 +63,8 @@ namespace readability {
class ReadabilityModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<ConditionaltostdminmaxCheck>(
+ "readability-ConditionalToStdMinMax");
CheckFactories.registerCheck<AvoidConstParamsInDecls>(
"readability-avoid-const-params-in-decls");
CheckFactories.registerCheck<AvoidReturnWithVoidValueCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b4d87e0ed2a67..c3fb990ad6a73 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -224,6 +224,12 @@ New checks
Recommends the smallest possible underlying type for an ``enum`` or ``enum``
class based on the range of its enumerators.
+- New :doc:`readability-ConditionalToStdMinMax
+ <clang-tidy/checks/readability/ConditionalToStdMinMax>` check.
+
+ Replaces certain conditional statements with equivalent std::min or std::max expressions,
+ improving readability and promoting the use of standard library functions.
+
- New :doc:`readability-reference-to-constructed-temporary
<clang-tidy/checks/readability/reference-to-constructed-temporary>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 2f86121ad8729..c2eac55425c69 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -336,6 +336,7 @@ Clang-Tidy Checks
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
+ :doc:`readability-ConditionalToStdMinMax <readability/ConditionalToStdMinMax>`, "Yes"
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`,
:doc:`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
new file mode 100644
index 0000000000000..e95858999b277
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
@@ -0,0 +1,29 @@
+.. title:: clang-tidy - readability-ConditionalToStdMinMax
+
+readability-ConditionalToStdMinMax
+==================================
+
+Replaces certain conditional statements with equivalent std::min or std::max expressions,
+improving readability and promoting the use of standard library functions.
+
+Examples:
+
+Before:
+
+.. code-block:: c++
+
+ void foo(){
+ int a,b;
+ if(a < b)
+ a = b;
+ }
+
+
+After:
+
+.. code-block:: c++
+
+ int main(){
+ a = std::max(a, b);
+
+ }
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp
new file mode 100644
index 0000000000000..d29e9aa9fec70
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp
@@ -0,0 +1,27 @@
+// RUN: %check_clang_tidy %s readability-ConditionalToStdMinMax %t
+
+void foo() {
+ int value1,value2;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::max instead of < [readability-ConditionalToStdMinMax]
+ if (value1 < value2)
+ value1 = value2; // CHECK-FIXES: value1 = std::max(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::min instead of < [readability-ConditionalToStdMinMax]
+ if (value1 < value2)
+ value2 = value1; // CHECK-FIXES: value2 = std::min(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::min instead of > [readability-ConditionalToStdMinMax]
+ if (value2 > value1)
+ value2 = value1; // CHECK-FIXES: value2 = std::min(value2, value1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::max instead of > [readability-ConditionalToStdMinMax]
+ if (value2 > value1)
+ value1 = value2; // CHECK-FIXES: value1 = std::max(value2, value1);
+
+ // No suggestion needed here
+ if (value1 == value2)
+ value1 = value2;
+
+
+}
\ No newline at end of file
>From 89be4baf2591918b11b633d2430050dc41068fde Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 00:03:16 +0530
Subject: [PATCH 02/47] Formatted the code
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../ConditionaltostdminmaxCheck.cpp | 96 ++++++++++---------
.../readability/ConditionaltostdminmaxCheck.h | 4 +-
2 files changed, 52 insertions(+), 48 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
index fba8c68f73745..86420765d6f6c 100644
--- a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
@@ -16,69 +16,71 @@ namespace clang::tidy::readability {
void ConditionaltostdminmaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- ifStmt(
- has(
- binaryOperator(
- anyOf(hasOperatorName("<"),hasOperatorName(">")),
- hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar1"))),
- hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar1")))
- )
- )
- ,
- hasThen(
- stmt(
- binaryOperator(
- hasOperatorName("="),
- hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar2"))),
- hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar2")))
- )
- )
- )
- ).bind("ifStmt"),this);
-
-
-
+ ifStmt(has(binaryOperator(
+ anyOf(hasOperatorName("<"), hasOperatorName(">")),
+ hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar1"))),
+ hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar1"))))),
+ hasThen(stmt(binaryOperator(
+ hasOperatorName("="),
+ hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar2"))),
+ hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar2")))))))
+ .bind("ifStmt"),
+ this);
}
-void ConditionaltostdminmaxCheck::check(const MatchFinder::MatchResult &Result) {
+void ConditionaltostdminmaxCheck::check(
+ const MatchFinder::MatchResult &Result) {
const DeclRefExpr *lhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar1");
const DeclRefExpr *rhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar1");
const DeclRefExpr *lhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar2");
- const DeclRefExpr *rhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar2");
+ const DeclRefExpr *rhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar2");
const IfStmt *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
- return;
+ return;
const BinaryOperator *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
if (!binaryOp)
- return;
+ return;
SourceLocation ifLocation = ifStmt->getIfLoc();
SourceLocation thenLocation = ifStmt->getEndLoc();
- if(binaryOp->getOpcode() == BO_LT){
- if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::max instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- }
- else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::min instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- }
- }
- else if(binaryOp->getOpcode() == BO_GT){
- if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::min instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
+ if (binaryOp->getOpcode() == BO_LT) {
+ if (lhsVar1->getDecl() == lhsVar2->getDecl() &&
+ rhsVar1->getDecl() == rhsVar2->getDecl()) {
+ diag(ifStmt->getIfLoc(), "use std::max instead of <")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::max(" +
+ lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ } else if (lhsVar1->getDecl() == rhsVar2->getDecl() &&
+ rhsVar1->getDecl() == lhsVar2->getDecl()) {
+ diag(ifStmt->getIfLoc(), "use std::min instead of <")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::min(" +
+ lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
}
- else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::max instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
+ } else if (binaryOp->getOpcode() == BO_GT) {
+ if (lhsVar1->getDecl() == lhsVar2->getDecl() &&
+ rhsVar1->getDecl() == rhsVar2->getDecl()) {
+ diag(ifStmt->getIfLoc(), "use std::min instead of >")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::min(" +
+ lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ } else if (lhsVar1->getDecl() == rhsVar2->getDecl() &&
+ rhsVar1->getDecl() == lhsVar2->getDecl()) {
+ diag(ifStmt->getIfLoc(), "use std::max instead of >")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::max(" +
+ lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
}
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
index b7eabcc7d16d4..02ebed83fed6c 100644
--- a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
@@ -13,7 +13,9 @@
namespace clang::tidy::readability {
-/// FIXME: replaces certain conditional statements with equivalent std::min or std::max expressions, improving readability and promoting the use of standard library functions."
+/// FIXME: replaces certain conditional statements with equivalent std::min or
+/// std::max expressions, improving readability and promoting the use of
+/// standard library functions."
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/ConditionalToStdMinMax.html
>From e1b65a9fb0ea27d62b568d8d3038c0231927cdad Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 00:15:54 +0530
Subject: [PATCH 03/47] small fix
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/checks/readability/ConditionalToStdMinMax.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
index e95858999b277..2b75e78ecb808 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
@@ -23,7 +23,7 @@ After:
.. code-block:: c++
- int main(){
+ void foo(){
a = std::max(a, b);
}
\ No newline at end of file
>From 042ddc3d89ebad999378e6bb8ef29e1f05f81745 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 15:43:22 +0530
Subject: [PATCH 04/47] Revert "small fix"
This reverts commit e1b65a9fb0ea27d62b568d8d3038c0231927cdad.
---
.../clang-tidy/checks/readability/ConditionalToStdMinMax.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
index 2b75e78ecb808..e95858999b277 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
@@ -23,7 +23,7 @@ After:
.. code-block:: c++
- void foo(){
+ int main(){
a = std::max(a, b);
}
\ No newline at end of file
>From c17b298185d50095d964d5afd8f79f52281e85f8 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 15:43:38 +0530
Subject: [PATCH 05/47] Revert "Formatted the code"
This reverts commit 89be4baf2591918b11b633d2430050dc41068fde.
---
.../ConditionaltostdminmaxCheck.cpp | 96 +++++++++----------
.../readability/ConditionaltostdminmaxCheck.h | 4 +-
2 files changed, 48 insertions(+), 52 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
index 86420765d6f6c..fba8c68f73745 100644
--- a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
@@ -16,71 +16,69 @@ namespace clang::tidy::readability {
void ConditionaltostdminmaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- ifStmt(has(binaryOperator(
- anyOf(hasOperatorName("<"), hasOperatorName(">")),
- hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar1"))),
- hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar1"))))),
- hasThen(stmt(binaryOperator(
- hasOperatorName("="),
- hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar2"))),
- hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar2")))))))
- .bind("ifStmt"),
- this);
+ ifStmt(
+ has(
+ binaryOperator(
+ anyOf(hasOperatorName("<"),hasOperatorName(">")),
+ hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar1"))),
+ hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar1")))
+ )
+ )
+ ,
+ hasThen(
+ stmt(
+ binaryOperator(
+ hasOperatorName("="),
+ hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar2"))),
+ hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar2")))
+ )
+ )
+ )
+ ).bind("ifStmt"),this);
+
+
+
}
-void ConditionaltostdminmaxCheck::check(
- const MatchFinder::MatchResult &Result) {
+void ConditionaltostdminmaxCheck::check(const MatchFinder::MatchResult &Result) {
const DeclRefExpr *lhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar1");
const DeclRefExpr *rhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar1");
const DeclRefExpr *lhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar2");
- const DeclRefExpr *rhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar2");
+ const DeclRefExpr *rhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar2");
const IfStmt *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
- return;
+ return;
const BinaryOperator *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
if (!binaryOp)
- return;
+ return;
SourceLocation ifLocation = ifStmt->getIfLoc();
SourceLocation thenLocation = ifStmt->getEndLoc();
- if (binaryOp->getOpcode() == BO_LT) {
- if (lhsVar1->getDecl() == lhsVar2->getDecl() &&
- rhsVar1->getDecl() == rhsVar2->getDecl()) {
- diag(ifStmt->getIfLoc(), "use std::max instead of <")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::max(" +
- lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- } else if (lhsVar1->getDecl() == rhsVar2->getDecl() &&
- rhsVar1->getDecl() == lhsVar2->getDecl()) {
- diag(ifStmt->getIfLoc(), "use std::min instead of <")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::min(" +
- lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
+ if(binaryOp->getOpcode() == BO_LT){
+ if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::max instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ }
+ else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::min instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
+ }
+ }
+ else if(binaryOp->getOpcode() == BO_GT){
+ if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::min instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
}
- } else if (binaryOp->getOpcode() == BO_GT) {
- if (lhsVar1->getDecl() == lhsVar2->getDecl() &&
- rhsVar1->getDecl() == rhsVar2->getDecl()) {
- diag(ifStmt->getIfLoc(), "use std::min instead of >")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::min(" +
- lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- } else if (lhsVar1->getDecl() == rhsVar2->getDecl() &&
- rhsVar1->getDecl() == lhsVar2->getDecl()) {
- diag(ifStmt->getIfLoc(), "use std::max instead of >")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::max(" +
- lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
+ else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
+ diag(ifStmt->getIfLoc(), "use std::max instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
+ rhsVar1->getNameInfo().getAsString() + ")");
}
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
index 02ebed83fed6c..b7eabcc7d16d4 100644
--- a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
@@ -13,9 +13,7 @@
namespace clang::tidy::readability {
-/// FIXME: replaces certain conditional statements with equivalent std::min or
-/// std::max expressions, improving readability and promoting the use of
-/// standard library functions."
+/// FIXME: replaces certain conditional statements with equivalent std::min or std::max expressions, improving readability and promoting the use of standard library functions."
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/ConditionalToStdMinMax.html
>From 9aad658ef0e6175cdc0388c914a444a5bcd9ba1c Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 15:43:52 +0530
Subject: [PATCH 06/47] Revert "Add readability check to suggest replacement of
conditional statement with std::min/std::max"
This reverts commit 1883d987b2f83adaef05fdb47ae25c7b06582a64.
---
.../clang-tidy/readability/CMakeLists.txt | 1 -
.../ConditionaltostdminmaxCheck.cpp | 86 -------------------
.../readability/ConditionaltostdminmaxCheck.h | 30 -------
.../readability/ReadabilityTidyModule.cpp | 3 -
clang-tools-extra/docs/ReleaseNotes.rst | 6 --
.../docs/clang-tidy/checks/list.rst | 1 -
.../readability/ConditionalToStdMinMax.rst | 29 -------
.../readability/ConditionalToStdMinMax.cpp | 27 ------
8 files changed, 183 deletions(-)
delete mode 100644 clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
delete mode 100644 clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
delete mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 4bc373bb69bb8..408c822b861c5 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -8,7 +8,6 @@ add_clang_library(clangTidyReadabilityModule
AvoidReturnWithVoidValueCheck.cpp
AvoidUnconditionalPreprocessorIfCheck.cpp
BracesAroundStatementsCheck.cpp
- ConditionaltostdminmaxCheck.cpp
ConstReturnTypeCheck.cpp
ContainerContainsCheck.cpp
ContainerDataPointerCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
deleted file mode 100644
index fba8c68f73745..0000000000000
--- a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===--- ConditionaltostdminmaxCheck.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 "ConditionaltostdminmaxCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang::tidy::readability {
-
-void ConditionaltostdminmaxCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(
- ifStmt(
- has(
- binaryOperator(
- anyOf(hasOperatorName("<"),hasOperatorName(">")),
- hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar1"))),
- hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar1")))
- )
- )
- ,
- hasThen(
- stmt(
- binaryOperator(
- hasOperatorName("="),
- hasLHS(ignoringImpCasts(declRefExpr().bind("lhsVar2"))),
- hasRHS(ignoringImpCasts(declRefExpr().bind("rhsVar2")))
- )
- )
- )
- ).bind("ifStmt"),this);
-
-
-
-}
-
-void ConditionaltostdminmaxCheck::check(const MatchFinder::MatchResult &Result) {
- const DeclRefExpr *lhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar1");
- const DeclRefExpr *rhsVar1 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar1");
- const DeclRefExpr *lhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("lhsVar2");
- const DeclRefExpr *rhsVar2 = Result.Nodes.getNodeAs<DeclRefExpr>("rhsVar2");
- const IfStmt *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
-
- if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
- return;
-
- const BinaryOperator *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
- if (!binaryOp)
- return;
-
- SourceLocation ifLocation = ifStmt->getIfLoc();
- SourceLocation thenLocation = ifStmt->getEndLoc();
-
- if(binaryOp->getOpcode() == BO_LT){
- if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::max instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- }
- else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::min instead of <")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- }
- }
- else if(binaryOp->getOpcode() == BO_GT){
- if(lhsVar1->getDecl() == lhsVar2->getDecl() && rhsVar1->getDecl() == rhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::min instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::min(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- }
- else if(lhsVar1->getDecl() == rhsVar2->getDecl() && rhsVar1->getDecl() == lhsVar2->getDecl()){
- diag(ifStmt->getIfLoc(), "use std::max instead of >")<<FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2->getNameInfo().getAsString() + " = std::max(" + lhsVar1->getNameInfo().getAsString() + ", " +
- rhsVar1->getNameInfo().getAsString() + ")");
- }
- }
-}
-
-} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h b/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
deleted file mode 100644
index b7eabcc7d16d4..0000000000000
--- a/clang-tools-extra/clang-tidy/readability/ConditionaltostdminmaxCheck.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===--- ConditionaltostdminmaxCheck.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_CONDITIONALTOSTDMINMAXCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_CONDITIONALTOSTDMINMAXCHECK_H
-
-#include "../ClangTidyCheck.h"
-
-namespace clang::tidy::readability {
-
-/// FIXME: replaces certain conditional statements with equivalent std::min or std::max expressions, improving readability and promoting the use of standard library functions."
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/readability/ConditionalToStdMinMax.html
-class ConditionaltostdminmaxCheck : public ClangTidyCheck {
-public:
- ConditionaltostdminmaxCheck(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_CONDITIONALTOSTDMINMAXCHECK_H
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 63f8f03be6bb9..0b0aad7c0dcb3 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -13,7 +13,6 @@
#include "AvoidReturnWithVoidValueCheck.h"
#include "AvoidUnconditionalPreprocessorIfCheck.h"
#include "BracesAroundStatementsCheck.h"
-#include "ConditionaltostdminmaxCheck.h"
#include "ConstReturnTypeCheck.h"
#include "ContainerContainsCheck.h"
#include "ContainerDataPointerCheck.h"
@@ -63,8 +62,6 @@ namespace readability {
class ReadabilityModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
- CheckFactories.registerCheck<ConditionaltostdminmaxCheck>(
- "readability-ConditionalToStdMinMax");
CheckFactories.registerCheck<AvoidConstParamsInDecls>(
"readability-avoid-const-params-in-decls");
CheckFactories.registerCheck<AvoidReturnWithVoidValueCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index c3fb990ad6a73..b4d87e0ed2a67 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -224,12 +224,6 @@ New checks
Recommends the smallest possible underlying type for an ``enum`` or ``enum``
class based on the range of its enumerators.
-- New :doc:`readability-ConditionalToStdMinMax
- <clang-tidy/checks/readability/ConditionalToStdMinMax>` check.
-
- Replaces certain conditional statements with equivalent std::min or std::max expressions,
- improving readability and promoting the use of standard library functions.
-
- New :doc:`readability-reference-to-constructed-temporary
<clang-tidy/checks/readability/reference-to-constructed-temporary>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index c2eac55425c69..2f86121ad8729 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -336,7 +336,6 @@ Clang-Tidy Checks
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
- :doc:`readability-ConditionalToStdMinMax <readability/ConditionalToStdMinMax>`, "Yes"
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`,
:doc:`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
deleted file mode 100644
index e95858999b277..0000000000000
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/ConditionalToStdMinMax.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-.. title:: clang-tidy - readability-ConditionalToStdMinMax
-
-readability-ConditionalToStdMinMax
-==================================
-
-Replaces certain conditional statements with equivalent std::min or std::max expressions,
-improving readability and promoting the use of standard library functions.
-
-Examples:
-
-Before:
-
-.. code-block:: c++
-
- void foo(){
- int a,b;
- if(a < b)
- a = b;
- }
-
-
-After:
-
-.. code-block:: c++
-
- int main(){
- a = std::max(a, b);
-
- }
\ No newline at end of file
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp
deleted file mode 100644
index d29e9aa9fec70..0000000000000
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/ConditionalToStdMinMax.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-// RUN: %check_clang_tidy %s readability-ConditionalToStdMinMax %t
-
-void foo() {
- int value1,value2;
-
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::max instead of < [readability-ConditionalToStdMinMax]
- if (value1 < value2)
- value1 = value2; // CHECK-FIXES: value1 = std::max(value1, value2);
-
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::min instead of < [readability-ConditionalToStdMinMax]
- if (value1 < value2)
- value2 = value1; // CHECK-FIXES: value2 = std::min(value1, value2);
-
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::min instead of > [readability-ConditionalToStdMinMax]
- if (value2 > value1)
- value2 = value1; // CHECK-FIXES: value2 = std::min(value2, value1);
-
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use std::max instead of > [readability-ConditionalToStdMinMax]
- if (value2 > value1)
- value1 = value2; // CHECK-FIXES: value1 = std::max(value2, value1);
-
- // No suggestion needed here
- if (value1 == value2)
- value1 = value2;
-
-
-}
\ No newline at end of file
>From 2fc0938430a25ca6672c2d408e55f5b1a3188d60 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 17:24:08 +0530
Subject: [PATCH 07/47] Added Suggested Changes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/readability/CMakeLists.txt | 1 +
.../readability/ReadabilityTidyModule.cpp | 3 +
.../readability/UseStdMinMaxCheck.cpp | 103 ++++++++++++++++++
.../readability/UseStdMinMaxCheck.h | 38 +++++++
clang-tools-extra/docs/ReleaseNotes.rst | 5 +
.../docs/clang-tidy/checks/list.rst | 1 +
.../checks/readability/UseStdMinMax.rst | 33 ++++++
.../checkers/readability/use-std-min-max.cpp | 35 ++++++
8 files changed, 219 insertions(+)
create mode 100644 clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
create mode 100644 clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
create mode 100644 clang-tools-extra/docs/clang-tidy/checks/readability/UseStdMinMax.rst
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 408c822b861c5..3670a43995434 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -52,6 +52,7 @@ add_clang_library(clangTidyReadabilityModule
UniqueptrDeleteReleaseCheck.cpp
UppercaseLiteralSuffixCheck.cpp
UseAnyOfAllOfCheck.cpp
+ UseStdMinMaxCheck.cpp
LINK_LIBS
clangTidy
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 0b0aad7c0dcb3..cba32ea24cec7 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -55,6 +55,7 @@
#include "UniqueptrDeleteReleaseCheck.h"
#include "UppercaseLiteralSuffixCheck.h"
#include "UseAnyOfAllOfCheck.h"
+#include "UseStdMinMaxCheck.h"
namespace clang::tidy {
namespace readability {
@@ -62,6 +63,8 @@ namespace readability {
class ReadabilityModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<UseStdMinMaxCheck>(
+ "readability-use-std-min-max");
CheckFactories.registerCheck<AvoidConstParamsInDecls>(
"readability-avoid-const-params-in-decls");
CheckFactories.registerCheck<AvoidReturnWithVoidValueCheck>(
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
new file mode 100644
index 0000000000000..984792322ce5d
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -0,0 +1,103 @@
+//===--- UseStdMinMaxCheck.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 "UseStdMinMaxCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Preprocessor.h"
+#include <optional>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ ifStmt(has(binaryOperator(
+ anyOf(hasOperatorName("<"), hasOperatorName(">"),hasOperatorName("<="), hasOperatorName(">=")),
+ hasLHS(expr().bind("lhsVar1")),
+ hasRHS(expr().bind("rhsVar1")))),
+ hasThen(stmt(binaryOperator(
+ hasOperatorName("="),
+ hasLHS(expr().bind("lhsVar2")),
+ hasRHS(expr().bind("rhsVar2"))))))
+ .bind("ifStmt"),
+ this);
+
+}
+
+void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *lhsVar1 = Result.Nodes.getNodeAs<Expr>("lhsVar1");
+ const auto *rhsVar1 = Result.Nodes.getNodeAs<Expr>("rhsVar1");
+ const auto *lhsVar2 = Result.Nodes.getNodeAs<Expr>("lhsVar2");
+ const auto *rhsVar2 = Result.Nodes.getNodeAs<Expr>("rhsVar2");
+ const auto *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
+ auto &Context = *Result.Context;
+
+ if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
+ return;
+
+ const BinaryOperator *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
+ if (!binaryOp)
+ return;
+
+ SourceLocation ifLocation = ifStmt->getIfLoc();
+ SourceLocation thenLocation = ifStmt->getEndLoc();
+ auto lhsVar1Str = Lexer::getSourceText(CharSourceRange::getTokenRange(lhsVar1->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
+
+ auto lhsVar2Str = Lexer::getSourceText(CharSourceRange::getTokenRange(lhsVar2->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
+
+ auto rhsVar1Str = Lexer::getSourceText(CharSourceRange::getTokenRange(rhsVar1->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
+
+ auto rhsVar2Str = Lexer::getSourceText(CharSourceRange::getTokenRange(rhsVar2->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
+
+ if (binaryOp->getOpcode() == BO_LT) {
+ if (lhsVar1Str == lhsVar2Str &&
+ rhsVar1Str == rhsVar2Str) {
+ diag(ifStmt->getIfLoc(), "use `std::max` instead of `<`")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::max(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
+ } else if (lhsVar1Str == rhsVar2Str &&
+ rhsVar1Str == lhsVar2Str) {
+ diag(ifStmt->getIfLoc(), "use `std::min` instead of `<`")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::min(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
+ }
+ } else if (binaryOp->getOpcode() == BO_GT) {
+ if (lhsVar1Str == lhsVar2Str &&
+ rhsVar1Str == rhsVar2Str) {
+ diag(ifStmt->getIfLoc(), "use `std::min` instead of `>`")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::min(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
+ } else if (lhsVar1Str == rhsVar2Str &&
+ rhsVar1Str == lhsVar2Str) {
+ diag(ifStmt->getIfLoc(), "use `std::max` instead of `>`")
+ << FixItHint::CreateReplacement(
+ SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::max(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
+ }
+ }
+
+}
+
+} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
new file mode 100644
index 0000000000000..476b19ba5c9cf
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -0,0 +1,38 @@
+//===--- UseStdMinMaxCheck.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_USESTDMINMAXCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USESTDMINMAXCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::readability {
+
+/// replaces certain conditional statements with equivalent ``std::min`` or
+/// ``std::max`` expressions, improving readability and promoting the use of
+/// standard library functions.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability/UseStdMinMax.html
+class UseStdMinMaxCheck : public ClangTidyCheck {
+public:
+ UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+ return LangOpts.CPlusPlus;
+ }
+ 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
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USESTDMINMAXCHECK_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b4d87e0ed2a67..2d3a2c2981e6c 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -224,6 +224,11 @@ New checks
Recommends the smallest possible underlying type for an ``enum`` or ``enum``
class based on the range of its enumerators.
+- New :doc:`readability-use-std-min-max
+ <clang-tidy/checks/readability/use-std-min-max>` check.
+
+ FIXME: add release notes.
+
- New :doc:`readability-reference-to-constructed-temporary
<clang-tidy/checks/readability/reference-to-constructed-temporary>` check.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 2f86121ad8729..25b3550a77e46 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -336,6 +336,7 @@ Clang-Tidy Checks
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
+ :doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`,
:doc:`readability-avoid-unconditional-preprocessor-if <readability/avoid-unconditional-preprocessor-if>`,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/UseStdMinMax.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/UseStdMinMax.rst
new file mode 100644
index 0000000000000..c8b9bdc7c5ea3
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/UseStdMinMax.rst
@@ -0,0 +1,33 @@
+.. title:: clang-tidy - readability-use-std-min-max
+
+readability-use-std-min-max
+========================
+
+Replaces certain conditional statements with equivalent ``std::min`` or ``std::max`` expressions,
+improving readability and promoting the use of standard library functions.
+Note: While this transformation improves code clarity, it may not be
+suitable for performance-critical code. Using ``std::min`` or ``std::max`` can
+introduce additional stores, potentially impacting performance compared to
+the original if statement that only assigns when the value needs to change.
+
+Examples:
+
+Before:
+
+.. code-block:: c++
+
+ void foo(){
+ int a,b;
+ if(a < b)
+ a = b;
+ }
+
+
+After:
+
+.. code-block:: c++
+
+ void foo(){
+ a = std::max(a, b);
+
+ }
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
new file mode 100644
index 0000000000000..37ee1fd65fb91
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -0,0 +1,35 @@
+// RUN: %check_clang_tidy %s readability-use-std-min-max %t
+
+void foo() {
+ int value1,value2,value3;
+ short value4;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ if (value1 < value2)
+ value1 = value2; // CHECK-FIXES: value1 = std::max(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ if (value1 < value2)
+ value2 = value1; // CHECK-FIXES: value2 = std::min(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ if (value2 > value1)
+ value2 = value1; // CHECK-FIXES: value2 = std::min(value2, value1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max
+ if (value2 > value1)
+ value1 = value2; // CHECK-FIXES: value1 = std::max(value2, value1);
+
+ // No suggestion needed here
+ if (value1 == value2)
+ value1 = value2;
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ if(value1<value4)
+ value1=value4; // CHECK-FIXES: value1 = std::max(value1, value4);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ if(value1+value2<value3)
+ value3 = value1+value2; // CHECK-FIXES: value3 = std::min(value1+value2, value3);
+
+}
\ No newline at end of file
>From 1139ac49be8023011bd57a2462781ac8b219c161 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 17:24:47 +0530
Subject: [PATCH 08/47] Formatted the Code
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 88 +++++++++----------
1 file changed, 41 insertions(+), 47 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 984792322ce5d..f203ec1e89b35 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -17,18 +17,17 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(
- ifStmt(has(binaryOperator(
- anyOf(hasOperatorName("<"), hasOperatorName(">"),hasOperatorName("<="), hasOperatorName(">=")),
- hasLHS(expr().bind("lhsVar1")),
- hasRHS(expr().bind("rhsVar1")))),
- hasThen(stmt(binaryOperator(
- hasOperatorName("="),
- hasLHS(expr().bind("lhsVar2")),
- hasRHS(expr().bind("rhsVar2"))))))
+ Finder->addMatcher(
+ ifStmt(
+ has(binaryOperator(
+ anyOf(hasOperatorName("<"), hasOperatorName(">"),
+ hasOperatorName("<="), hasOperatorName(">=")),
+ hasLHS(expr().bind("lhsVar1")), hasRHS(expr().bind("rhsVar1")))),
+ hasThen(stmt(binaryOperator(hasOperatorName("="),
+ hasLHS(expr().bind("lhsVar2")),
+ hasRHS(expr().bind("rhsVar2"))))))
.bind("ifStmt"),
this);
-
}
void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
@@ -48,56 +47,51 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
SourceLocation ifLocation = ifStmt->getIfLoc();
SourceLocation thenLocation = ifStmt->getEndLoc();
- auto lhsVar1Str = Lexer::getSourceText(CharSourceRange::getTokenRange(lhsVar1->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto lhsVar1Str = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(lhsVar1->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
- auto lhsVar2Str = Lexer::getSourceText(CharSourceRange::getTokenRange(lhsVar2->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto lhsVar2Str = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(lhsVar2->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
- auto rhsVar1Str = Lexer::getSourceText(CharSourceRange::getTokenRange(rhsVar1->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto rhsVar1Str = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(rhsVar1->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
- auto rhsVar2Str = Lexer::getSourceText(CharSourceRange::getTokenRange(rhsVar2->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto rhsVar2Str = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(rhsVar2->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
if (binaryOp->getOpcode() == BO_LT) {
- if (lhsVar1Str == lhsVar2Str &&
- rhsVar1Str == rhsVar2Str) {
+ if (lhsVar1Str == lhsVar2Str && rhsVar1Str == rhsVar2Str) {
diag(ifStmt->getIfLoc(), "use `std::max` instead of `<`")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::max(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
- } else if (lhsVar1Str == rhsVar2Str &&
- rhsVar1Str == lhsVar2Str) {
+ << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::max(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
+ } else if (lhsVar1Str == rhsVar2Str && rhsVar1Str == lhsVar2Str) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `<`")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::min(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
+ << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::min(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
}
} else if (binaryOp->getOpcode() == BO_GT) {
- if (lhsVar1Str == lhsVar2Str &&
- rhsVar1Str == rhsVar2Str) {
+ if (lhsVar1Str == lhsVar2Str && rhsVar1Str == rhsVar2Str) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `>`")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::min(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
- } else if (lhsVar1Str == rhsVar2Str &&
- rhsVar1Str == lhsVar2Str) {
+ << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::min(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
+ } else if (lhsVar1Str == rhsVar2Str && rhsVar1Str == lhsVar2Str) {
diag(ifStmt->getIfLoc(), "use `std::max` instead of `>`")
- << FixItHint::CreateReplacement(
- SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::max(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
+ << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
+ lhsVar2Str.str() + " = std::max(" +
+ lhsVar1Str.str() + ", " +
+ rhsVar1Str.str() + ")");
}
}
-
}
} // namespace clang::tidy::readability
>From f73e9f019a03f5f864e952ddbad288d9a11b801e Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 17:27:10 +0530
Subject: [PATCH 09/47] Added Release Notes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
clang-tools-extra/docs/ReleaseNotes.rst | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2d3a2c2981e6c..314e0eb69f793 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -227,7 +227,9 @@ New checks
- New :doc:`readability-use-std-min-max
<clang-tidy/checks/readability/use-std-min-max>` check.
- FIXME: add release notes.
+ Replaces certain conditional statements with equivalent ``std::min`` or
+ ``std::max`` expressions, improving readability and promoting the use of
+ standard library functions.
- New :doc:`readability-reference-to-constructed-temporary
<clang-tidy/checks/readability/reference-to-constructed-temporary>` check.
>From faf3312b6d6713cb9af43ae09ca66f3ac05878bf Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 17:31:38 +0530
Subject: [PATCH 10/47] corrected file name
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../checks/readability/{UseStdMinMax.rst => use-std-min-max.rst} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename clang-tools-extra/docs/clang-tidy/checks/readability/{UseStdMinMax.rst => use-std-min-max.rst} (100%)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/UseStdMinMax.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
similarity index 100%
rename from clang-tools-extra/docs/clang-tidy/checks/readability/UseStdMinMax.rst
rename to clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
>From 5ed9896cffdbf057b4e8088a37c98a50e0e4d946 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 17:35:44 +0530
Subject: [PATCH 11/47] corrected title length in docs
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../docs/clang-tidy/checks/readability/use-std-min-max.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index c8b9bdc7c5ea3..573beeeb2a842 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -1,7 +1,7 @@
.. title:: clang-tidy - readability-use-std-min-max
readability-use-std-min-max
-========================
+===========================
Replaces certain conditional statements with equivalent ``std::min`` or ``std::max`` expressions,
improving readability and promoting the use of standard library functions.
>From 19c4b63da4a183f661a6e06fabc78aaf4e2868e4 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 21:54:46 +0530
Subject: [PATCH 12/47] Suggested Changes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 2 +-
.../checks/readability/use-std-min-max.rst | 22 +++++++++----------
.../checkers/readability/use-std-min-max.cpp | 1 -
3 files changed, 11 insertions(+), 14 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index f203ec1e89b35..1a4392523cf18 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -41,7 +41,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
return;
- const BinaryOperator *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
+ const auto *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
if (!binaryOp)
return;
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index 573beeeb2a842..2364acacbaffd 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -5,10 +5,8 @@ readability-use-std-min-max
Replaces certain conditional statements with equivalent ``std::min`` or ``std::max`` expressions,
improving readability and promoting the use of standard library functions.
-Note: While this transformation improves code clarity, it may not be
-suitable for performance-critical code. Using ``std::min`` or ``std::max`` can
-introduce additional stores, potentially impacting performance compared to
-the original if statement that only assigns when the value needs to change.
+Note: this transformation may impact performance in performance-critical code due to potential
+additional stores compared to the original if statement.
Examples:
@@ -16,18 +14,18 @@ Before:
.. code-block:: c++
- void foo(){
- int a,b;
- if(a < b)
- a = b;
- }
+ void foo() {
+ int a, b;
+ if (a < b)
+ a = b;
+ }
After:
.. code-block:: c++
- void foo(){
- a = std::max(a, b);
-
+ void foo() {
+ int a, b;
+ a = std::max(a, b);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 37ee1fd65fb91..b65e3a9b27cc2 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -31,5 +31,4 @@ void foo() {
// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
if(value1+value2<value3)
value3 = value1+value2; // CHECK-FIXES: value3 = std::min(value1+value2, value3);
-
}
\ No newline at end of file
>From 8167787453886874b8e458f040c878ad7e711016 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 12 Jan 2024 22:35:17 +0530
Subject: [PATCH 13/47] body indentation
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/checks/readability/use-std-min-max.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index 2364acacbaffd..de22f069d2192 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -15,9 +15,9 @@ Before:
.. code-block:: c++
void foo() {
- int a, b;
- if (a < b)
- a = b;
+ int a, b;
+ if (a < b)
+ a = b;
}
@@ -26,6 +26,6 @@ After:
.. code-block:: c++
void foo() {
- int a, b;
- a = std::max(a, b);
+ int a, b;
+ a = std::max(a, b);
}
>From 3a28399a08b4625abe7d08dee82fbee850de534e Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sat, 13 Jan 2024 21:17:23 +0530
Subject: [PATCH 14/47] added intialisation,constexpr tests
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../checks/readability/use-std-min-max.rst | 4 ++--
.../checkers/readability/use-std-min-max.cpp | 23 +++++++++++++++++++
2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index de22f069d2192..0d621d4d4477f 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -15,7 +15,7 @@ Before:
.. code-block:: c++
void foo() {
- int a, b;
+ int a = 2, b = 3;
if (a < b)
a = b;
}
@@ -26,6 +26,6 @@ After:
.. code-block:: c++
void foo() {
- int a, b;
+ int a = 2, b = 3;
a = std::max(a, b);
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index b65e3a9b27cc2..1dc48ffc63cfb 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -1,5 +1,16 @@
// RUN: %check_clang_tidy %s readability-use-std-min-max %t
+constexpr int myConstexprMin(int a, int b) {
+ return a < b ? a : b;
+}
+
+constexpr int myConstexprMax(int a, int b) {
+ return a > b ? a : b;
+}
+
+int bar(int x, int y) {
+ return x < y ? x : y;
+}
void foo() {
int value1,value2,value3;
short value4;
@@ -31,4 +42,16 @@ void foo() {
// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
if(value1+value2<value3)
value3 = value1+value2; // CHECK-FIXES: value3 = std::min(value1+value2, value3);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ if (value1 < myConstexprMin(value2, value3))
+ value1 = myConstexprMin(value2, value3); // CHECK-FIXES: value1 = std::max(value1, myConstexprMin(value2, value3));
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ if (value1 > myConstexprMax(value2, value3))
+ value1 = myConstexprMax(value2, value3); // CHECK-FIXES: value1 = std::min(value1, myConstexprMax(value2, value3));
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ if (value1 < bar(value2, value3))
+ value1 = bar(value2, value3); // CHECK-FIXES: value1 = std::max(value1, bar(value2, value3));
}
\ No newline at end of file
>From 2ecd08a149d60b9dfdc54d777bf10b34758054a8 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sat, 13 Jan 2024 21:32:22 +0530
Subject: [PATCH 15/47] small fixes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/checks/readability/use-std-min-max.rst | 9 +++++----
.../clang-tidy/checkers/readability/use-std-min-max.cpp | 1 +
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index 0d621d4d4477f..7e64a05ccd8b8 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -3,10 +3,11 @@
readability-use-std-min-max
===========================
-Replaces certain conditional statements with equivalent ``std::min`` or ``std::max`` expressions,
-improving readability and promoting the use of standard library functions.
-Note: this transformation may impact performance in performance-critical code due to potential
-additional stores compared to the original if statement.
+Replaces certain conditionals with ``std::min`` or ``std::max`` for readability,
+promoting use of standard library functions. Note: This may impact
+performance in critical code due to potential additional stores compared
+to the original if statement.
+
Examples:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 1dc48ffc63cfb..9525d5e1f2489 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -11,6 +11,7 @@ constexpr int myConstexprMax(int a, int b) {
int bar(int x, int y) {
return x < y ? x : y;
}
+
void foo() {
int value1,value2,value3;
short value4;
>From 00d4080a6a1f4af2b79b748ff60527aae10c9f97 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 15 Jan 2024 21:12:17 +0530
Subject: [PATCH 16/47] Addded Suggested Changes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 50 +++++++--------
.../readability/UseStdMinMaxCheck.h | 2 +-
.../checkers/readability/use-std-min-max.cpp | 63 +++++++++++++++++++
3 files changed, 88 insertions(+), 27 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 1a4392523cf18..833d27d4957b3 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -8,6 +8,7 @@
#include "UseStdMinMaxCheck.h"
#include "clang/AST/ASTContext.h"
+#include "../utils/ASTUtils.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Preprocessor.h"
#include <optional>
@@ -47,6 +48,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
SourceLocation ifLocation = ifStmt->getIfLoc();
SourceLocation thenLocation = ifStmt->getEndLoc();
+
auto lhsVar1Str = Lexer::getSourceText(
CharSourceRange::getTokenRange(lhsVar1->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
@@ -58,38 +60,34 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
auto rhsVar1Str = Lexer::getSourceText(
CharSourceRange::getTokenRange(rhsVar1->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
+
+ auto replacementMax = lhsVar2Str.str() + " = std::max(" + lhsVar1Str.str() + ", " + rhsVar1Str.str() + ")";
+ auto replacementMin = lhsVar2Str.str() + " = std::min(" + lhsVar1Str.str() + ", " + rhsVar1Str.str() + ")";
+ auto *operatorStr = binaryOp->getOpcodeStr().data();
- auto rhsVar2Str = Lexer::getSourceText(
- CharSourceRange::getTokenRange(rhsVar2->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
-
- if (binaryOp->getOpcode() == BO_LT) {
- if (lhsVar1Str == lhsVar2Str && rhsVar1Str == rhsVar2Str) {
- diag(ifStmt->getIfLoc(), "use `std::max` instead of `<`")
+ if (binaryOp->getOpcode() == BO_LT || binaryOp->getOpcode() == BO_LE) {
+ if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2,Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2,Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::max(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
- } else if (lhsVar1Str == rhsVar2Str && rhsVar1Str == lhsVar2Str) {
- diag(ifStmt->getIfLoc(), "use `std::min` instead of `<`")
+ std::move(replacementMax));
+ } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2,Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2,Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::min(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
+ std::move(replacementMin));
}
- } else if (binaryOp->getOpcode() == BO_GT) {
- if (lhsVar1Str == lhsVar2Str && rhsVar1Str == rhsVar2Str) {
- diag(ifStmt->getIfLoc(), "use `std::min` instead of `>`")
+ } else if (binaryOp->getOpcode() == BO_GT || binaryOp->getOpcode() == BO_GE) {
+ if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2,Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2,Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::min(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
- } else if (lhsVar1Str == rhsVar2Str && rhsVar1Str == lhsVar2Str) {
- diag(ifStmt->getIfLoc(), "use `std::max` instead of `>`")
+ std::move(replacementMin));
+ } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2,Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2,Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- lhsVar2Str.str() + " = std::max(" +
- lhsVar1Str.str() + ", " +
- rhsVar1Str.str() + ")");
+ std::move(replacementMax));
}
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index 476b19ba5c9cf..d6f4fdf40ea30 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -13,7 +13,7 @@
namespace clang::tidy::readability {
-/// replaces certain conditional statements with equivalent ``std::min`` or
+/// Replaces certain conditional statements with equivalent ``std::min`` or
/// ``std::max`` expressions, improving readability and promoting the use of
/// standard library functions.
///
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 9525d5e1f2489..99be29fb163bb 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -12,9 +12,16 @@ int bar(int x, int y) {
return x < y ? x : y;
}
+class MyClass {
+public:
+ int member1;
+ int member2;
+};
+
void foo() {
int value1,value2,value3;
short value4;
+ MyClass obj;
// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
if (value1 < value2)
@@ -55,4 +62,60 @@ void foo() {
// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
if (value1 < bar(value2, value3))
value1 = bar(value2, value3); // CHECK-FIXES: value1 = std::max(value1, bar(value2, value3));
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
+ if (value1 <= value2)
+ value2 = value1; // CHECK-FIXES: value2 = std::min(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
+ if (value1 <= value2)
+ value1 = value2; // CHECK-FIXES: value1 = std::max(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
+ if (value2 >= value1)
+ value1 = value2; // CHECK-FIXES: value1 = std::max(value2, value1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
+ if (value2 >= value1)
+ value2 = value1; // CHECK-FIXES: value2 = std::min(value2, value1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ if (obj.member1 < obj.member2)
+ obj.member1 = obj.member2; // CHECK-FIXES: obj.member1 = std::max(obj.member1, obj.member2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ if (obj.member1 < obj.member2)
+ obj.member2 = obj.member1; // CHECK-FIXES: obj.member2 = std::min(obj.member1, obj.member2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ if (obj.member2 > obj.member1)
+ obj.member2 = obj.member1; // CHECK-FIXES: obj.member2 = std::min(obj.member2, obj.member1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
+ if (obj.member2 > obj.member1)
+ obj.member1 = obj.member2; // CHECK-FIXES: obj.member1 = std::max(obj.member2, obj.member1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ if (obj.member1 < value4)
+ obj.member1 = value4; // CHECK-FIXES: obj.member1 = std::max(obj.member1, value4);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ if (obj.member1 + value2 < value3)
+ value3 = obj.member1 + value2; // CHECK-FIXES: value3 = std::min(obj.member1 + value2, value3);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
+ if (value1 <= obj.member2)
+ obj.member2 = value1; // CHECK-FIXES: obj.member2 = std::min(value1, obj.member2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
+ if (value1 <= obj.member2)
+ value1 = obj.member2; // CHECK-FIXES: value1 = std::max(value1, obj.member2);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
+ if (obj.member2 >= value1)
+ value1 = obj.member2; // CHECK-FIXES: value1 = std::max(obj.member2, value1);
+
+ // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
+ if (obj.member2 >= value1)
+ obj.member2 = value1; // CHECK-FIXES: obj.member2 = std::min(obj.member2, value1);
}
\ No newline at end of file
>From 6db08204966b52862ecdcf5ff829fe06e266b882 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 15 Jan 2024 21:12:41 +0530
Subject: [PATCH 17/47] formatted the code
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 46 +++++++++++--------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 833d27d4957b3..2f7a8d944a504 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "UseStdMinMaxCheck.h"
-#include "clang/AST/ASTContext.h"
#include "../utils/ASTUtils.h"
+#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Preprocessor.h"
#include <optional>
@@ -60,34 +60,40 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
auto rhsVar1Str = Lexer::getSourceText(
CharSourceRange::getTokenRange(rhsVar1->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
-
- auto replacementMax = lhsVar2Str.str() + " = std::max(" + lhsVar1Str.str() + ", " + rhsVar1Str.str() + ")";
- auto replacementMin = lhsVar2Str.str() + " = std::min(" + lhsVar1Str.str() + ", " + rhsVar1Str.str() + ")";
+
+ auto replacementMax = lhsVar2Str.str() + " = std::max(" + lhsVar1Str.str() +
+ ", " + rhsVar1Str.str() + ")";
+ auto replacementMin = lhsVar2Str.str() + " = std::min(" + lhsVar1Str.str() +
+ ", " + rhsVar1Str.str() + ")";
auto *operatorStr = binaryOp->getOpcodeStr().data();
if (binaryOp->getOpcode() == BO_LT || binaryOp->getOpcode() == BO_LE) {
- if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2,Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2,Context)) {
- diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")<< operatorStr
+ if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2, Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
+ << operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax));
- } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2,Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2,Context)) {
- diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")<< operatorStr
+ std::move(replacementMax));
+ } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
+ << operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin));
+ std::move(replacementMin));
}
} else if (binaryOp->getOpcode() == BO_GT || binaryOp->getOpcode() == BO_GE) {
- if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2,Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2,Context)) {
- diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")<< operatorStr
+ if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2, Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
+ << operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin));
- } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2,Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2,Context)) {
- diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")<< operatorStr
+ std::move(replacementMin));
+ } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
+ tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
+ diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
+ << operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax));
+ std::move(replacementMax));
}
}
}
>From 5073650de12a6588cd171bccfc67f6298065f82e Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 16 Jan 2024 03:38:20 +0530
Subject: [PATCH 18/47] Added Include Check
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 26 ++++++++++++++++---
.../readability/UseStdMinMaxCheck.h | 11 +++++---
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 2f7a8d944a504..b7f9f65c71ad6 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -17,6 +17,16 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
+UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+ utils::IncludeSorter::IS_LLVM),
+ areDiagsSelfContained()),AlgotithmHeader(Options.get("AlgorithmHeader","<algorithm>")) {}
+
+void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+}
+
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
ifStmt(
@@ -31,6 +41,12 @@ void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
this);
}
+void UseStdMinMaxCheck::registerPPCallbacks(const SourceManager &SM,
+ Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) {
+ IncludeInserter.registerPreprocessor(PP);
+}
+
void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *lhsVar1 = Result.Nodes.getNodeAs<Expr>("lhsVar1");
const auto *rhsVar1 = Result.Nodes.getNodeAs<Expr>("rhsVar1");
@@ -38,6 +54,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *rhsVar2 = Result.Nodes.getNodeAs<Expr>("rhsVar2");
const auto *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
auto &Context = *Result.Context;
+ const SourceManager &Source = Context.getSourceManager();
if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
return;
@@ -70,16 +87,17 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (binaryOp->getOpcode() == BO_LT || binaryOp->getOpcode() == BO_LE) {
if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2, Context)) {
+
diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax));
+ std::move(replacementMax))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
} else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin));
+ std::move(replacementMin))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
}
} else if (binaryOp->getOpcode() == BO_GT || binaryOp->getOpcode() == BO_GE) {
if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
@@ -87,13 +105,13 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin));
+ std::move(replacementMin))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
} else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax));
+ std::move(replacementMax))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
}
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index d6f4fdf40ea30..c92e80a351e1b 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -10,7 +10,7 @@
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_USESTDMINMAXCHECK_H
#include "../ClangTidyCheck.h"
-
+#include "../utils/IncludeInserter.h"
namespace clang::tidy::readability {
/// Replaces certain conditional statements with equivalent ``std::min`` or
@@ -21,16 +21,21 @@ namespace clang::tidy::readability {
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/UseStdMinMax.html
class UseStdMinMaxCheck : public ClangTidyCheck {
public:
- UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
+ UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context);
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
+ void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
+ Preprocessor *ModuleExpanderPP) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
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;
}
+ private:
+ utils::IncludeInserter IncludeInserter;
+ StringRef AlgotithmHeader;
};
} // namespace clang::tidy::readability
>From c728a39c8a11fc17130a49c6d472fff2133ce6dc Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 16 Jan 2024 03:38:52 +0530
Subject: [PATCH 19/47] Formatted the code
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 21 +++++++++++++------
.../readability/UseStdMinMaxCheck.h | 3 ++-
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index b7f9f65c71ad6..15e26f9baf68b 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -21,7 +21,8 @@ UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::IS_LLVM),
- areDiagsSelfContained()),AlgotithmHeader(Options.get("AlgorithmHeader","<algorithm>")) {}
+ areDiagsSelfContained()),
+ AlgotithmHeader(Options.get("AlgorithmHeader", "<algorithm>")) {}
void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
@@ -87,17 +88,21 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (binaryOp->getOpcode() == BO_LT || binaryOp->getOpcode() == BO_LE) {
if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2, Context)) {
-
+
diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ std::move(replacementMax))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
} else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ std::move(replacementMin))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
}
} else if (binaryOp->getOpcode() == BO_GT || binaryOp->getOpcode() == BO_GE) {
if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
@@ -105,13 +110,17 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ std::move(replacementMin))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
} else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
<< operatorStr
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax))<<IncludeInserter.createIncludeInsertion(Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ std::move(replacementMax))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
}
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index c92e80a351e1b..4146d9455bcd1 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -33,7 +33,8 @@ class UseStdMinMaxCheck : public ClangTidyCheck {
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
}
- private:
+
+private:
utils::IncludeInserter IncludeInserter;
StringRef AlgotithmHeader;
};
>From b8202aefe3e5cb07f59b7fc0d7647820987bde4b Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Wed, 17 Jan 2024 16:44:02 +0530
Subject: [PATCH 20/47] Added tests for macro & if with brackets
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 42 +++---
.../readability/UseStdMinMaxCheck.h | 2 +-
.../checkers/readability/use-std-min-max.cpp | 132 +++++++++++-------
3 files changed, 104 insertions(+), 72 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 15e26f9baf68b..1b0adc2ac6876 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -22,7 +22,7 @@ UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::IS_LLVM),
areDiagsSelfContained()),
- AlgotithmHeader(Options.get("AlgorithmHeader", "<algorithm>")) {}
+ AlgorithmHeader(Options.get("AlgorithmHeader", "<algorithm>")) {}
void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
@@ -35,9 +35,13 @@ void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
anyOf(hasOperatorName("<"), hasOperatorName(">"),
hasOperatorName("<="), hasOperatorName(">=")),
hasLHS(expr().bind("lhsVar1")), hasRHS(expr().bind("rhsVar1")))),
- hasThen(stmt(binaryOperator(hasOperatorName("="),
- hasLHS(expr().bind("lhsVar2")),
- hasRHS(expr().bind("rhsVar2"))))))
+ hasThen(
+ anyOf(stmt(binaryOperator(hasOperatorName("="),
+ hasLHS(expr().bind("lhsVar2")),
+ hasRHS(expr().bind("rhsVar2")))),
+ compoundStmt(has(binaryOperator(
+ hasOperatorName("="), hasLHS(expr().bind("lhsVar2")),
+ hasRHS(expr().bind("rhsVar2"))))))))
.bind("ifStmt"),
this);
}
@@ -67,22 +71,22 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
SourceLocation ifLocation = ifStmt->getIfLoc();
SourceLocation thenLocation = ifStmt->getEndLoc();
- auto lhsVar1Str = Lexer::getSourceText(
- CharSourceRange::getTokenRange(lhsVar1->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto lhsVar1Str =
+ Lexer::getSourceText(Source.getExpansionRange(lhsVar1->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
- auto lhsVar2Str = Lexer::getSourceText(
- CharSourceRange::getTokenRange(lhsVar2->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto lhsVar2Str =
+ Lexer::getSourceText(Source.getExpansionRange(lhsVar2->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
- auto rhsVar1Str = Lexer::getSourceText(
- CharSourceRange::getTokenRange(rhsVar1->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ auto rhsVar1Str =
+ Lexer::getSourceText(Source.getExpansionRange(rhsVar1->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
auto replacementMax = lhsVar2Str.str() + " = std::max(" + lhsVar1Str.str() +
- ", " + rhsVar1Str.str() + ")";
+ ", " + rhsVar1Str.str() + ");";
auto replacementMin = lhsVar2Str.str() + " = std::min(" + lhsVar1Str.str() +
- ", " + rhsVar1Str.str() + ")";
+ ", " + rhsVar1Str.str() + ");";
auto *operatorStr = binaryOp->getOpcodeStr().data();
if (binaryOp->getOpcode() == BO_LT || binaryOp->getOpcode() == BO_LE) {
@@ -94,7 +98,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
std::move(replacementMax))
<< IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
} else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
@@ -102,7 +106,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
std::move(replacementMin))
<< IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
}
} else if (binaryOp->getOpcode() == BO_GT || binaryOp->getOpcode() == BO_GE) {
if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
@@ -112,7 +116,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
std::move(replacementMin))
<< IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
} else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
@@ -120,7 +124,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
<< FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
std::move(replacementMax))
<< IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgotithmHeader);
+ Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
}
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index 4146d9455bcd1..52b34fdbe2627 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -36,7 +36,7 @@ class UseStdMinMaxCheck : public ClangTidyCheck {
private:
utils::IncludeInserter IncludeInserter;
- StringRef AlgotithmHeader;
+ StringRef AlgorithmHeader;
};
} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 99be29fb163bb..4a43d8f3926d4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -1,5 +1,7 @@
// RUN: %check_clang_tidy %s readability-use-std-min-max %t
+#define MY_MACRO_MIN(a, b) ((a) < (b) ? (a) : (b))
+
constexpr int myConstexprMin(int a, int b) {
return a < b ? a : b;
}
@@ -8,10 +10,6 @@ constexpr int myConstexprMax(int a, int b) {
return a > b ? a : b;
}
-int bar(int x, int y) {
- return x < y ? x : y;
-}
-
class MyClass {
public:
int member1;
@@ -23,99 +21,129 @@ void foo() {
short value4;
MyClass obj;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value1, value2);
if (value1 < value2)
- value1 = value2; // CHECK-FIXES: value1 = std::max(value1, value2);
+ value1 = value2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value2 = std::min(value1, value2);
if (value1 < value2)
- value2 = value1; // CHECK-FIXES: value2 = std::min(value1, value2);
+ value2 = value1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ // CHECK-FIXES: value2 = std::min(value2, value1);
if (value2 > value1)
- value2 = value1; // CHECK-FIXES: value2 = std::min(value2, value1);
+ value2 = value1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max
+ // CHECK-FIXES: value1 = std::max(value2, value1);
if (value2 > value1)
- value1 = value2; // CHECK-FIXES: value1 = std::max(value2, value1);
+ value1 = value2;
// No suggestion needed here
if (value1 == value2)
value1 = value2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value1, value4);
if(value1<value4)
- value1=value4; // CHECK-FIXES: value1 = std::max(value1, value4);
+ value1=value4;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value3 = std::min(value1+value2, value3);
if(value1+value2<value3)
- value3 = value1+value2; // CHECK-FIXES: value3 = std::min(value1+value2, value3);
+ value3 = value1+value2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value1, myConstexprMin(value2, value3));
if (value1 < myConstexprMin(value2, value3))
- value1 = myConstexprMin(value2, value3); // CHECK-FIXES: value1 = std::max(value1, myConstexprMin(value2, value3));
+ value1 = myConstexprMin(value2, value3);
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::min(value1, myConstexprMax(value2, value3));
if (value1 > myConstexprMax(value2, value3))
- value1 = myConstexprMax(value2, value3); // CHECK-FIXES: value1 = std::min(value1, myConstexprMax(value2, value3));
-
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- if (value1 < bar(value2, value3))
- value1 = bar(value2, value3); // CHECK-FIXES: value1 = std::max(value1, bar(value2, value3));
+ value1 = myConstexprMax(value2, value3);
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
+ // CHECK-FIXES: value2 = std::min(value1, value2);
if (value1 <= value2)
- value2 = value1; // CHECK-FIXES: value2 = std::min(value1, value2);
+ value2 = value1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value1, value2);
if (value1 <= value2)
- value1 = value2; // CHECK-FIXES: value1 = std::max(value1, value2);
+ value1 = value2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value2, value1);
if (value2 >= value1)
- value1 = value2; // CHECK-FIXES: value1 = std::max(value2, value1);
+ value1 = value2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
+ // CHECK-FIXES: value2 = std::min(value2, value1);
if (value2 >= value1)
- value2 = value1; // CHECK-FIXES: value2 = std::min(value2, value1);
+ value2 = value1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member1 = std::max(obj.member1, obj.member2);
if (obj.member1 < obj.member2)
- obj.member1 = obj.member2; // CHECK-FIXES: obj.member1 = std::max(obj.member1, obj.member2);
+ obj.member1 = obj.member2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member2 = std::min(obj.member1, obj.member2);
if (obj.member1 < obj.member2)
- obj.member2 = obj.member1; // CHECK-FIXES: obj.member2 = std::min(obj.member1, obj.member2);
+ obj.member2 = obj.member1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member2 = std::min(obj.member2, obj.member1);
if (obj.member2 > obj.member1)
- obj.member2 = obj.member1; // CHECK-FIXES: obj.member2 = std::min(obj.member2, obj.member1);
+ obj.member2 = obj.member1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member1 = std::max(obj.member2, obj.member1);
if (obj.member2 > obj.member1)
- obj.member1 = obj.member2; // CHECK-FIXES: obj.member1 = std::max(obj.member2, obj.member1);
+ obj.member1 = obj.member2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member1 = std::max(obj.member1, value4);
if (obj.member1 < value4)
- obj.member1 = value4; // CHECK-FIXES: obj.member1 = std::max(obj.member1, value4);
+ obj.member1 = value4;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value3 = std::min(obj.member1 + value2, value3);
if (obj.member1 + value2 < value3)
- value3 = obj.member1 + value2; // CHECK-FIXES: value3 = std::min(obj.member1 + value2, value3);
+ value3 = obj.member1 + value2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member2 = std::min(value1, obj.member2);
if (value1 <= obj.member2)
- obj.member2 = value1; // CHECK-FIXES: obj.member2 = std::min(value1, obj.member2);
+ obj.member2 = value1;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value1, obj.member2);
if (value1 <= obj.member2)
- value1 = obj.member2; // CHECK-FIXES: value1 = std::max(value1, obj.member2);
+ value1 = obj.member2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(obj.member2, value1);
if (obj.member2 >= value1)
- value1 = obj.member2; // CHECK-FIXES: value1 = std::max(obj.member2, value1);
+ value1 = obj.member2;
- // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
+ // CHECK-FIXES: obj.member2 = std::min(obj.member2, value1);
if (obj.member2 >= value1)
- obj.member2 = value1; // CHECK-FIXES: obj.member2 = std::min(obj.member2, value1);
+ obj.member2 = value1;
+
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value3 = std::min(MY_MACRO_MIN(value1, value2), value3);
+ if (MY_MACRO_MIN(value1, value2) < value3)
+ value3 = MY_MACRO_MIN(value1, value2);
+
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value2 = std::min(value1, value2);
+ if (value1 < value2){
+ value2 = value1;
+ }
+
}
\ No newline at end of file
>From 5e31665d0c449ae09d21b409bbf8b1e035f553b7 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 19 Jan 2024 13:06:27 +0530
Subject: [PATCH 21/47] Added suggested changes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 136 +++++++++---------
clang-tools-extra/docs/ReleaseNotes.rst | 3 +-
.../checkers/readability/use-std-min-max.cpp | 30 +++-
3 files changed, 96 insertions(+), 73 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 1b0adc2ac6876..88bd2e1a941b8 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -21,28 +21,27 @@ UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
utils::IncludeSorter::IS_LLVM),
- areDiagsSelfContained()),
- AlgorithmHeader(Options.get("AlgorithmHeader", "<algorithm>")) {}
+ areDiagsSelfContained()) {}
void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
+ Options.store(Opts, "AlgorithmHeader", Options.get("AlgorithmHeader", "<algorithm>"));
}
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
ifStmt(
- has(binaryOperator(
- anyOf(hasOperatorName("<"), hasOperatorName(">"),
- hasOperatorName("<="), hasOperatorName(">=")),
- hasLHS(expr().bind("lhsVar1")), hasRHS(expr().bind("rhsVar1")))),
+ hasCondition(binaryOperator(
+ hasAnyOperatorName("<",">","<=",">="),
+ hasLHS(expr().bind("CondLhs")), hasRHS(expr().bind("CondRhs")))),
hasThen(
anyOf(stmt(binaryOperator(hasOperatorName("="),
- hasLHS(expr().bind("lhsVar2")),
- hasRHS(expr().bind("rhsVar2")))),
+ hasLHS(expr().bind("AssignLhs")),
+ hasRHS(expr().bind("AssignRhs")))),
compoundStmt(has(binaryOperator(
- hasOperatorName("="), hasLHS(expr().bind("lhsVar2")),
- hasRHS(expr().bind("rhsVar2"))))))))
- .bind("ifStmt"),
+ hasOperatorName("="), hasLHS(expr().bind("AssignLhs")),
+ hasRHS(expr().bind("AssignRhs"))))).bind("compound"))))
+ .bind("if"),
this);
}
@@ -53,79 +52,78 @@ void UseStdMinMaxCheck::registerPPCallbacks(const SourceManager &SM,
}
void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *lhsVar1 = Result.Nodes.getNodeAs<Expr>("lhsVar1");
- const auto *rhsVar1 = Result.Nodes.getNodeAs<Expr>("rhsVar1");
- const auto *lhsVar2 = Result.Nodes.getNodeAs<Expr>("lhsVar2");
- const auto *rhsVar2 = Result.Nodes.getNodeAs<Expr>("rhsVar2");
- const auto *ifStmt = Result.Nodes.getNodeAs<IfStmt>("ifStmt");
+ const auto *CondLhs = Result.Nodes.getNodeAs<Expr>("CondLhs");
+ const auto *CondRhs = Result.Nodes.getNodeAs<Expr>("CondRhs");
+ const auto *AssignLhs = Result.Nodes.getNodeAs<Expr>("AssignLhs");
+ const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
+ const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
+ const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
auto &Context = *Result.Context;
const SourceManager &Source = Context.getSourceManager();
- if (!lhsVar1 || !rhsVar1 || !lhsVar2 || !rhsVar2 || !ifStmt)
+ const auto *BinaryOp = dyn_cast<BinaryOperator>(If->getCond());
+ if (!BinaryOp || If->hasElseStorage())
return;
+
+ if(Compound){
+ int count = 0;
+ clang::Stmt::const_child_iterator I = Compound->child_begin();
+ clang::Stmt::const_child_iterator E = Compound->child_end();
+ for(; I != E; ++I){count++;}
+ if(count>1)
+ return;
- const auto *binaryOp = dyn_cast<BinaryOperator>(ifStmt->getCond());
- if (!binaryOp)
- return;
+ }
- SourceLocation ifLocation = ifStmt->getIfLoc();
- SourceLocation thenLocation = ifStmt->getEndLoc();
+ SourceLocation IfLocation = If->getIfLoc();
+ SourceLocation ThenLocation = If->getEndLoc();
- auto lhsVar1Str =
- Lexer::getSourceText(Source.getExpansionRange(lhsVar1->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ if(IfLocation.isMacroID() || ThenLocation.isMacroID())
+ return;
- auto lhsVar2Str =
- Lexer::getSourceText(Source.getExpansionRange(lhsVar2->getSourceRange()),
+ const auto CondLhsStr =
+ Lexer::getSourceText(Source.getExpansionRange(CondLhs->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
- auto rhsVar1Str =
- Lexer::getSourceText(Source.getExpansionRange(rhsVar1->getSourceRange()),
+ const auto AssignLhsStr =
+ Lexer::getSourceText(Source.getExpansionRange(AssignLhs->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
- auto replacementMax = lhsVar2Str.str() + " = std::max(" + lhsVar1Str.str() +
- ", " + rhsVar1Str.str() + ");";
- auto replacementMin = lhsVar2Str.str() + " = std::min(" + lhsVar1Str.str() +
- ", " + rhsVar1Str.str() + ");";
- auto *operatorStr = binaryOp->getOpcodeStr().data();
-
- if (binaryOp->getOpcode() == BO_LT || binaryOp->getOpcode() == BO_LE) {
- if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2, Context)) {
+ const auto CondRhsStr =
+ Lexer::getSourceText(Source.getExpansionRange(CondRhs->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
- diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
- << operatorStr
- << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax))
+ auto CreateMaxReplacement = [&]() {
+ return AssignLhsStr.str() + " = std::max(" + CondLhsStr.str() +
+ ", " + CondRhsStr.str() + ");";
+ };
+
+ auto CreateMinReplacement = [&]() {
+ return AssignLhsStr.str() + " = std::min(" + CondLhsStr.str() +
+ ", " + CondRhsStr.str() + ");";
+ };
+ const auto OperatorStr = BinaryOp->getOpcodeStr();
+ if(((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) || ((BinaryOp->getOpcode() == BO_GT || BinaryOp->getOpcode() == BO_GE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))){
+ diag(IfLocation, "use `std::min` instead of `%0`")
+ << OperatorStr
+ << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
+ std::move(CreateMinReplacement()))
<< IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
- } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
- diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
- << operatorStr
- << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin))
- << IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
- }
- } else if (binaryOp->getOpcode() == BO_GT || binaryOp->getOpcode() == BO_GE) {
- if (tidy::utils::areStatementsIdentical(lhsVar1, lhsVar2, Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, rhsVar2, Context)) {
- diag(ifStmt->getIfLoc(), "use `std::min` instead of `%0`")
- << operatorStr
- << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMin))
- << IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
- } else if (tidy::utils::areStatementsIdentical(lhsVar1, rhsVar2, Context) &&
- tidy::utils::areStatementsIdentical(rhsVar1, lhsVar2, Context)) {
- diag(ifStmt->getIfLoc(), "use `std::max` instead of `%0`")
- << operatorStr
- << FixItHint::CreateReplacement(SourceRange(ifLocation, thenLocation),
- std::move(replacementMax))
+ Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+
+ }
+ else if(((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context))) || ((BinaryOp->getOpcode() == BO_GT || BinaryOp->getOpcode() == BO_GE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context)))){
+ diag(IfLocation, "use `std::max` instead of `%0`")
+ << OperatorStr
+ << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
+ std::move(CreateMaxReplacement()))
<< IncludeInserter.createIncludeInsertion(
- Source.getFileID(ifStmt->getBeginLoc()), AlgorithmHeader);
- }
+ Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+
}
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 9f96001514ac3..3592411084e6a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -228,8 +228,7 @@ New checks
<clang-tidy/checks/readability/use-std-min-max>` check.
Replaces certain conditional statements with equivalent ``std::min`` or
- ``std::max`` expressions, improving readability and promoting the use of
- standard library functions.
+ ``std::max`` expressions.
- New :doc:`readability-avoid-nested-conditional-operator
<clang-tidy/checks/readability/avoid-nested-conditional-operator>` check.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 4a43d8f3926d4..03971fc4c56cd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -10,6 +10,11 @@ constexpr int myConstexprMax(int a, int b) {
return a > b ? a : b;
}
+#define MY_IF_MACRO(condition, statement) \
+ if (condition) { \
+ statement \
+ }
+
class MyClass {
public:
int member1;
@@ -135,8 +140,7 @@ void foo() {
if (obj.member2 >= value1)
obj.member2 = value1;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value3 = std::min(MY_MACRO_MIN(value1, value2), value3);
+ // No suggestion needed here
if (MY_MACRO_MIN(value1, value2) < value3)
value3 = MY_MACRO_MIN(value1, value2);
@@ -146,4 +150,26 @@ void foo() {
value2 = value1;
}
+ // No suggestion needed here
+ if(value1 < value2)
+ value2 = value1;
+ else
+ value2 = value3;
+
+ // No suggestion needed here
+ if(value1<value2){
+ value2 = value1;
+ }
+ else{
+ value2 = value3;
+ }
+
+ // No suggestion needed here
+ if(value1<value2){
+ value2 = value1;
+ int res = value1 + value2;
+ }
+
+ // No suggestion needed here
+ MY_IF_MACRO(value1 < value2, value1 = value2;)
}
\ No newline at end of file
>From a2cfcdcdcc14a95f89aa40378487a2812e6b04a8 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 19 Jan 2024 13:07:48 +0530
Subject: [PATCH 22/47] Formatted the code
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 103 ++++++++++--------
1 file changed, 58 insertions(+), 45 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 88bd2e1a941b8..4f684f5bcc16f 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -25,22 +25,24 @@ UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
- Options.store(Opts, "AlgorithmHeader", Options.get("AlgorithmHeader", "<algorithm>"));
+ Options.store(Opts, "AlgorithmHeader",
+ Options.get("AlgorithmHeader", "<algorithm>"));
}
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
ifStmt(
- hasCondition(binaryOperator(
- hasAnyOperatorName("<",">","<=",">="),
- hasLHS(expr().bind("CondLhs")), hasRHS(expr().bind("CondRhs")))),
- hasThen(
- anyOf(stmt(binaryOperator(hasOperatorName("="),
- hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs")))),
- compoundStmt(has(binaryOperator(
- hasOperatorName("="), hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs"))))).bind("compound"))))
+ hasCondition(binaryOperator(hasAnyOperatorName("<", ">", "<=", ">="),
+ hasLHS(expr().bind("CondLhs")),
+ hasRHS(expr().bind("CondRhs")))),
+ hasThen(anyOf(stmt(binaryOperator(hasOperatorName("="),
+ hasLHS(expr().bind("AssignLhs")),
+ hasRHS(expr().bind("AssignRhs")))),
+ compoundStmt(has(binaryOperator(
+ hasOperatorName("="),
+ hasLHS(expr().bind("AssignLhs")),
+ hasRHS(expr().bind("AssignRhs")))))
+ .bind("compound"))))
.bind("if"),
this);
}
@@ -64,66 +66,77 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *BinaryOp = dyn_cast<BinaryOperator>(If->getCond());
if (!BinaryOp || If->hasElseStorage())
return;
-
- if(Compound){
+
+ if (Compound) {
int count = 0;
clang::Stmt::const_child_iterator I = Compound->child_begin();
clang::Stmt::const_child_iterator E = Compound->child_end();
- for(; I != E; ++I){count++;}
- if(count>1)
+ for (; I != E; ++I) {
+ count++;
+ }
+ if (count > 1)
return;
-
}
SourceLocation IfLocation = If->getIfLoc();
SourceLocation ThenLocation = If->getEndLoc();
- if(IfLocation.isMacroID() || ThenLocation.isMacroID())
+ if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
const auto CondLhsStr =
Lexer::getSourceText(Source.getExpansionRange(CondLhs->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
- const auto AssignLhsStr =
- Lexer::getSourceText(Source.getExpansionRange(AssignLhs->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
+ const auto AssignLhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(AssignLhs->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts());
const auto CondRhsStr =
Lexer::getSourceText(Source.getExpansionRange(CondRhs->getSourceRange()),
Context.getSourceManager(), Context.getLangOpts());
auto CreateMaxReplacement = [&]() {
- return AssignLhsStr.str() + " = std::max(" + CondLhsStr.str() +
- ", " + CondRhsStr.str() + ");";
+ return AssignLhsStr.str() + " = std::max(" + CondLhsStr.str() + ", " +
+ CondRhsStr.str() + ");";
};
auto CreateMinReplacement = [&]() {
- return AssignLhsStr.str() + " = std::min(" + CondLhsStr.str() +
- ", " + CondRhsStr.str() + ");";
+ return AssignLhsStr.str() + " = std::min(" + CondLhsStr.str() + ", " +
+ CondRhsStr.str() + ");";
};
const auto OperatorStr = BinaryOp->getOpcodeStr();
- if(((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) || ((BinaryOp->getOpcode() == BO_GT || BinaryOp->getOpcode() == BO_GE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))){
- diag(IfLocation, "use `std::min` instead of `%0`")
- << OperatorStr
- << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- std::move(CreateMinReplacement()))
- << IncludeInserter.createIncludeInsertion(
- Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
-
- }
- else if(((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context))) || ((BinaryOp->getOpcode() == BO_GT || BinaryOp->getOpcode() == BO_GE) && (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context)))){
- diag(IfLocation, "use `std::max` instead of `%0`")
- << OperatorStr
- << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- std::move(CreateMaxReplacement()))
- << IncludeInserter.createIncludeInsertion(
- Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
-
+ if (((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) ||
+ ((BinaryOp->getOpcode() == BO_GT || BinaryOp->getOpcode() == BO_GE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))) {
+ diag(IfLocation, "use `std::min` instead of `%0`")
+ << OperatorStr
+ << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
+ std::move(CreateMinReplacement()))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+
+ } else if (((BinaryOp->getOpcode() == BO_LT ||
+ BinaryOp->getOpcode() == BO_LE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs,
+ Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs,
+ Context))) ||
+ ((BinaryOp->getOpcode() == BO_GT ||
+ BinaryOp->getOpcode() == BO_GE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs,
+ Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs,
+ Context)))) {
+ diag(IfLocation, "use `std::max` instead of `%0`")
+ << OperatorStr
+ << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
+ std::move(CreateMaxReplacement()))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
}
}
>From f5a0f12bbf59e141b4a0832a73d76a9be402ff14 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sat, 20 Jan 2024 01:55:16 +0530
Subject: [PATCH 23/47] Converted to Lambdas,placed at sorted location
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/ReadabilityTidyModule.cpp | 4 +-
.../readability/UseStdMinMaxCheck.cpp | 56 +++++++++----------
clang-tools-extra/docs/ReleaseNotes.rst | 12 ++--
.../docs/clang-tidy/checks/list.rst | 2 +-
4 files changed, 35 insertions(+), 39 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
index 89999e2794d2b..1cc520b0c005a 100644
--- a/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -64,8 +64,6 @@ namespace readability {
class ReadabilityModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
- CheckFactories.registerCheck<UseStdMinMaxCheck>(
- "readability-use-std-min-max");
CheckFactories.registerCheck<AvoidConstParamsInDecls>(
"readability-avoid-const-params-in-decls");
CheckFactories.registerCheck<AvoidNestedConditionalOperatorCheck>(
@@ -160,6 +158,8 @@ class ReadabilityModule : public ClangTidyModule {
"readability-uppercase-literal-suffix");
CheckFactories.registerCheck<UseAnyOfAllOfCheck>(
"readability-use-anyofallof");
+ CheckFactories.registerCheck<UseStdMinMaxCheck>(
+ "readability-use-std-min-max");
}
};
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 4f684f5bcc16f..44173515842e4 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -60,7 +60,8 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
- auto &Context = *Result.Context;
+ const auto &Context = *Result.Context;
+ const auto &LO = Context.getLangOpts();
const SourceManager &Source = Context.getSourceManager();
const auto *BinaryOp = dyn_cast<BinaryOperator>(If->getCond());
@@ -68,42 +69,37 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
return;
if (Compound) {
- int count = 0;
- clang::Stmt::const_child_iterator I = Compound->child_begin();
- clang::Stmt::const_child_iterator E = Compound->child_end();
- for (; I != E; ++I) {
- count++;
- }
- if (count > 1)
+ if (Compound->size() > 1)
return;
}
- SourceLocation IfLocation = If->getIfLoc();
- SourceLocation ThenLocation = If->getEndLoc();
+ const SourceLocation IfLocation = If->getIfLoc();
+ const SourceLocation ThenLocation = If->getEndLoc();
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
- const auto CondLhsStr =
- Lexer::getSourceText(Source.getExpansionRange(CondLhs->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
-
- const auto AssignLhsStr = Lexer::getSourceText(
- Source.getExpansionRange(AssignLhs->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
-
- const auto CondRhsStr =
- Lexer::getSourceText(Source.getExpansionRange(CondRhs->getSourceRange()),
- Context.getSourceManager(), Context.getLangOpts());
-
- auto CreateMaxReplacement = [&]() {
- return AssignLhsStr.str() + " = std::max(" + CondLhsStr.str() + ", " +
- CondRhsStr.str() + ");";
+ const auto CreateString = [&](int index) -> llvm::StringRef {
+ switch (index) {
+ case 1:
+ return Lexer::getSourceText(
+ Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
+ case 2:
+ return Lexer::getSourceText(
+ Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
+ case 3:
+ return Lexer::getSourceText(
+ Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
+ default:
+ return "Invalid index";
+ }
};
- auto CreateMinReplacement = [&]() {
- return AssignLhsStr.str() + " = std::min(" + CondLhsStr.str() + ", " +
- CondRhsStr.str() + ");";
+ const auto CreateReplacement = [&](bool useMax) {
+ std::string functionName = useMax ? "std::max" : "std::min";
+ return CreateString(/* AssignLhs */ 3).str() + " = " + functionName + "(" +
+ CreateString(/* CondLhs */ 1).str() + ", " +
+ CreateString(/* CondRhs */ 2).str() + ");";
};
const auto OperatorStr = BinaryOp->getOpcodeStr();
if (((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) &&
@@ -115,7 +111,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(IfLocation, "use `std::min` instead of `%0`")
<< OperatorStr
<< FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- std::move(CreateMinReplacement()))
+ CreateReplacement(/*useMax = false*/ 0))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
@@ -134,7 +130,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(IfLocation, "use `std::max` instead of `%0`")
<< OperatorStr
<< FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- std::move(CreateMaxReplacement()))
+ CreateReplacement(/*useMax = true*/ 1))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3592411084e6a..e258f4978c45f 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -224,12 +224,6 @@ New checks
Recommends the smallest possible underlying type for an ``enum`` or ``enum``
class based on the range of its enumerators.
-- New :doc:`readability-use-std-min-max
- <clang-tidy/checks/readability/use-std-min-max>` check.
-
- Replaces certain conditional statements with equivalent ``std::min`` or
- ``std::max`` expressions.
-
- New :doc:`readability-avoid-nested-conditional-operator
<clang-tidy/checks/readability/avoid-nested-conditional-operator>` check.
@@ -247,6 +241,12 @@ New checks
Detects C++ code where a reference variable is used to extend the lifetime
of a temporary object that has just been constructed.
+- New :doc:`readability-use-std-min-max
+ <clang-tidy/checks/readability/use-std-min-max>` check.
+
+ Replaces certain conditional statements with equivalent ``std::min`` or
+ ``std::max`` expressions.
+
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 3bd414f0eed89..68360eb67ac55 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -336,7 +336,6 @@ Clang-Tidy Checks
:doc:`portability-restrict-system-includes <portability/restrict-system-includes>`, "Yes"
:doc:`portability-simd-intrinsics <portability/simd-intrinsics>`,
:doc:`portability-std-allocator-const <portability/std-allocator-const>`,
- :doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
:doc:`readability-avoid-const-params-in-decls <readability/avoid-const-params-in-decls>`, "Yes"
:doc:`readability-avoid-nested-conditional-operator <readability/avoid-nested-conditional-operator>`,
:doc:`readability-avoid-return-with-void-value <readability/avoid-return-with-void-value>`,
@@ -384,6 +383,7 @@ Clang-Tidy Checks
:doc:`readability-uniqueptr-delete-release <readability/uniqueptr-delete-release>`, "Yes"
:doc:`readability-uppercase-literal-suffix <readability/uppercase-literal-suffix>`, "Yes"
:doc:`readability-use-anyofallof <readability/use-anyofallof>`,
+ :doc:`readability-use-std-min-max <readability/use-std-min-max>`, "Yes"
:doc:`zircon-temporary-objects <zircon/temporary-objects>`,
>From e239576831f3592fd35ed4628da1809026b621f8 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sat, 20 Jan 2024 22:54:37 +0530
Subject: [PATCH 24/47] Single Lambda
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 32 +++++++------------
.../checks/readability/use-std-min-max.rst | 4 +--
2 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 44173515842e4..9d740db05001e 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -79,27 +79,17 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
- const auto CreateString = [&](int index) -> llvm::StringRef {
- switch (index) {
- case 1:
- return Lexer::getSourceText(
- Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
- case 2:
- return Lexer::getSourceText(
- Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
- case 3:
- return Lexer::getSourceText(
- Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- default:
- return "Invalid index";
- }
- };
-
const auto CreateReplacement = [&](bool useMax) {
std::string functionName = useMax ? "std::max" : "std::min";
- return CreateString(/* AssignLhs */ 3).str() + " = " + functionName + "(" +
- CreateString(/* CondLhs */ 1).str() + ", " +
- CreateString(/* CondRhs */ 2).str() + ");";
+ const auto CondLhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
+ const auto CondRhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
+ const auto AssignLhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
+ return (AssignLhsStr + " = " + functionName + "(" + CondLhsStr + ", " +
+ CondRhsStr + ");")
+ .str();
};
const auto OperatorStr = BinaryOp->getOpcodeStr();
if (((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) &&
@@ -111,7 +101,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(IfLocation, "use `std::min` instead of `%0`")
<< OperatorStr
<< FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- CreateReplacement(/*useMax = false*/ 0))
+ CreateReplacement(/*useMax=*/false))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
@@ -130,7 +120,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(IfLocation, "use `std::max` instead of `%0`")
<< OperatorStr
<< FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- CreateReplacement(/*useMax = true*/ 1))
+ CreateReplacement(/*useMax=*/true))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
}
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index 7e64a05ccd8b8..2cf6a58552cde 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -3,8 +3,8 @@
readability-use-std-min-max
===========================
-Replaces certain conditionals with ``std::min`` or ``std::max`` for readability,
-promoting use of standard library functions. Note: This may impact
+Replaces certain conditional statements with equivalent ``std::min`` or
+``std::max`` expressions. Note: This may impact
performance in critical code due to potential additional stores compared
to the original if statement.
>From b868d5b5c3c5057eaec066ad6efa86e39aaf63e2 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 21 Jan 2024 00:20:19 +0530
Subject: [PATCH 25/47] CamelCase,const auto*
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/readability/UseStdMinMaxCheck.cpp | 10 +++++-----
.../clang-tidy/readability/UseStdMinMaxCheck.h | 4 +---
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 9d740db05001e..aa8a43631eb6f 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -79,15 +79,15 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
- const auto CreateReplacement = [&](bool useMax) {
- std::string functionName = useMax ? "std::max" : "std::min";
+ const auto CreateReplacement = [&](bool UseMax) {
+ const auto *FunctionName = UseMax ? "std::max" : "std::min";
const auto CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
const auto CondRhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
const auto AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- return (AssignLhsStr + " = " + functionName + "(" + CondLhsStr + ", " +
+ return (AssignLhsStr + " = " + FunctionName + "(" + CondLhsStr + ", " +
CondRhsStr + ");")
.str();
};
@@ -101,7 +101,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(IfLocation, "use `std::min` instead of `%0`")
<< OperatorStr
<< FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- CreateReplacement(/*useMax=*/false))
+ CreateReplacement(/*UseMax=*/false))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
@@ -120,7 +120,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
diag(IfLocation, "use `std::max` instead of `%0`")
<< OperatorStr
<< FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- CreateReplacement(/*useMax=*/true))
+ CreateReplacement(/*UseMax=*/true))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index 52b34fdbe2627..b4afe35696823 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -14,9 +14,7 @@
namespace clang::tidy::readability {
/// Replaces certain conditional statements with equivalent ``std::min`` or
-/// ``std::max`` expressions, improving readability and promoting the use of
-/// standard library functions.
-///
+/// ``std::max`` expressions.
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/UseStdMinMax.html
class UseStdMinMaxCheck : public ClangTidyCheck {
>From 0797e0c0f7a078de137e7e3e719afa9d70c061dd Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 21 Jan 2024 01:19:46 +0530
Subject: [PATCH 26/47] fixes
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 22 +++++---
.../readability/UseStdMinMaxCheck.h | 1 -
.../checkers/readability/use-std-min-max.cpp | 52 +++++++++----------
3 files changed, 40 insertions(+), 35 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index aa8a43631eb6f..a870235207fdd 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -17,6 +17,8 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
+static const llvm::StringRef AlgorithmHeader("<algorithm>");
+
UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
@@ -25,8 +27,6 @@ UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
- Options.store(Opts, "AlgorithmHeader",
- Options.get("AlgorithmHeader", "<algorithm>"));
}
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
@@ -87,8 +87,10 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
const auto AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- return (AssignLhsStr + " = " + FunctionName + "(" + CondLhsStr + ", " +
- CondRhsStr + ");")
+ const auto AssignLhsType =
+ AssignLhs->getType().getCanonicalType().getAsString();
+ return (AssignLhsStr + " = " + FunctionName + "<" + AssignLhsType + ">(" +
+ CondLhsStr + ", " + CondRhsStr + ");")
.str();
};
const auto OperatorStr = BinaryOp->getOpcodeStr();
@@ -100,8 +102,10 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))) {
diag(IfLocation, "use `std::min` instead of `%0`")
<< OperatorStr
- << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- CreateReplacement(/*UseMax=*/false))
+ << FixItHint::CreateReplacement(
+ SourceRange(IfLocation, Lexer::getLocForEndOfToken(
+ ThenLocation, 0, Source, LO)),
+ CreateReplacement(/*UseMax=*/false))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
@@ -119,8 +123,10 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
Context)))) {
diag(IfLocation, "use `std::max` instead of `%0`")
<< OperatorStr
- << FixItHint::CreateReplacement(SourceRange(IfLocation, ThenLocation),
- CreateReplacement(/*UseMax=*/true))
+ << FixItHint::CreateReplacement(
+ SourceRange(IfLocation, Lexer::getLocForEndOfToken(
+ ThenLocation, 0, Source, LO)),
+ CreateReplacement(/*UseMax=*/true))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index b4afe35696823..860e47794a99c 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -34,7 +34,6 @@ class UseStdMinMaxCheck : public ClangTidyCheck {
private:
utils::IncludeInserter IncludeInserter;
- StringRef AlgorithmHeader;
};
} // namespace clang::tidy::readability
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 03971fc4c56cd..6249957e3076c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -27,22 +27,22 @@ void foo() {
MyClass obj;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(value1, value2);
+ // CHECK-FIXES: value1 = std::max<int>(value1, value2);
if (value1 < value2)
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min(value1, value2);
+ // CHECK-FIXES: value2 = std::min<int>(value1, value2);
if (value1 < value2)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min(value2, value1);
+ // CHECK-FIXES: value2 = std::min<int>(value2, value1);
if (value2 > value1)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max
- // CHECK-FIXES: value1 = std::max(value2, value1);
+ // CHECK-FIXES: value1 = std::max<int>(value2, value1);
if (value2 > value1)
value1 = value2;
@@ -51,92 +51,92 @@ void foo() {
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(value1, value4);
+ // CHECK-FIXES: value1 = std::max<int>(value1, value4);
if(value1<value4)
value1=value4;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value3 = std::min(value1+value2, value3);
+ // CHECK-FIXES: value3 = std::min<int>(value1+value2, value3);
if(value1+value2<value3)
value3 = value1+value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(value1, myConstexprMin(value2, value3));
+ // CHECK-FIXES: value1 = std::max<int>(value1, myConstexprMin(value2, value3));
if (value1 < myConstexprMin(value2, value3))
value1 = myConstexprMin(value2, value3);
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::min(value1, myConstexprMax(value2, value3));
+ // CHECK-FIXES: value1 = std::min<int>(value1, myConstexprMax(value2, value3));
if (value1 > myConstexprMax(value2, value3))
value1 = myConstexprMax(value2, value3);
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min(value1, value2);
+ // CHECK-FIXES: value2 = std::min<int>(value1, value2);
if (value1 <= value2)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(value1, value2);
+ // CHECK-FIXES: value1 = std::max<int>(value1, value2);
if (value1 <= value2)
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(value2, value1);
+ // CHECK-FIXES: value1 = std::max<int>(value2, value1);
if (value2 >= value1)
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min(value2, value1);
+ // CHECK-FIXES: value2 = std::min<int>(value2, value1);
if (value2 >= value1)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member1 = std::max(obj.member1, obj.member2);
+ // CHECK-FIXES: obj.member1 = std::max<int>(obj.member1, obj.member2);
if (obj.member1 < obj.member2)
obj.member1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min(obj.member1, obj.member2);
+ // CHECK-FIXES: obj.member2 = std::min<int>(obj.member1, obj.member2);
if (obj.member1 < obj.member2)
obj.member2 = obj.member1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min(obj.member2, obj.member1);
+ // CHECK-FIXES: obj.member2 = std::min<int>(obj.member2, obj.member1);
if (obj.member2 > obj.member1)
obj.member2 = obj.member1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member1 = std::max(obj.member2, obj.member1);
+ // CHECK-FIXES: obj.member1 = std::max<int>(obj.member2, obj.member1);
if (obj.member2 > obj.member1)
obj.member1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member1 = std::max(obj.member1, value4);
+ // CHECK-FIXES: obj.member1 = std::max<int>(obj.member1, value4);
if (obj.member1 < value4)
obj.member1 = value4;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value3 = std::min(obj.member1 + value2, value3);
+ // CHECK-FIXES: value3 = std::min<int>(obj.member1 + value2, value3);
if (obj.member1 + value2 < value3)
value3 = obj.member1 + value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min(value1, obj.member2);
+ // CHECK-FIXES: obj.member2 = std::min<int>(value1, obj.member2);
if (value1 <= obj.member2)
obj.member2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(value1, obj.member2);
+ // CHECK-FIXES: value1 = std::max<int>(value1, obj.member2);
if (value1 <= obj.member2)
value1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max(obj.member2, value1);
+ // CHECK-FIXES: value1 = std::max<int>(obj.member2, value1);
if (obj.member2 >= value1)
value1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min(obj.member2, value1);
+ // CHECK-FIXES: obj.member2 = std::min<int>(obj.member2, value1);
if (obj.member2 >= value1)
obj.member2 = value1;
@@ -144,10 +144,10 @@ void foo() {
if (MY_MACRO_MIN(value1, value2) < value3)
value3 = MY_MACRO_MIN(value1, value2);
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min(value1, value2);
- if (value1 < value2){
- value2 = value1;
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value4 = std::max<short>(value4, value2);
+ if (value4 < value2){
+ value4 = value2;
}
// No suggestion needed here
>From c6028b0ddd8ce1ace6e6c3f14244e889250a8e34 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 21 Jan 2024 21:26:25 +0530
Subject: [PATCH 27/47] few nits
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 29 +++++++-------
.../checkers/readability/use-std-min-max.cpp | 40 +++++++++----------
2 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index a870235207fdd..6e39ebeda2b2c 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -11,7 +11,6 @@
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Preprocessor.h"
-#include <optional>
using namespace clang::ast_matchers;
@@ -38,11 +37,11 @@ void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
hasThen(anyOf(stmt(binaryOperator(hasOperatorName("="),
hasLHS(expr().bind("AssignLhs")),
hasRHS(expr().bind("AssignRhs")))),
- compoundStmt(has(binaryOperator(
+ compoundStmt(statementCountIs(1),
+ has(binaryOperator(
hasOperatorName("="),
hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs")))))
- .bind("compound"))))
+ hasRHS(expr().bind("AssignRhs"))))))))
.bind("if"),
this);
}
@@ -59,7 +58,6 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *AssignLhs = Result.Nodes.getNodeAs<Expr>("AssignLhs");
const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
- const auto *Compound = Result.Nodes.getNodeAs<CompoundStmt>("compound");
const auto &Context = *Result.Context;
const auto &LO = Context.getLangOpts();
const SourceManager &Source = Context.getSourceManager();
@@ -68,11 +66,6 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (!BinaryOp || If->hasElseStorage())
return;
- if (Compound) {
- if (Compound->size() > 1)
- return;
- }
-
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
@@ -87,11 +80,17 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
const auto AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- const auto AssignLhsType =
- AssignLhs->getType().getCanonicalType().getAsString();
- return (AssignLhsStr + " = " + FunctionName + "<" + AssignLhsType + ">(" +
- CondLhsStr + ", " + CondRhsStr + ");")
- .str();
+ if (CondLhs->getType() != CondRhs->getType()) {
+ return (AssignLhsStr + " = " + FunctionName + "<" +
+ AssignLhs->getType().getAsString() + ">(" + CondLhsStr + ", " +
+ CondRhsStr + ");")
+ .str();
+ } else {
+ return (AssignLhsStr + " = " + FunctionName + "(" + CondLhsStr + ", " +
+ CondRhsStr + ");")
+ .str();
+ }
+
};
const auto OperatorStr = BinaryOp->getOpcodeStr();
if (((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) &&
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 6249957e3076c..cdb169fd42c6f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -27,22 +27,22 @@ void foo() {
MyClass obj;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max<int>(value1, value2);
+ // CHECK-FIXES: value1 = std::max(value1, value2);
if (value1 < value2)
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min<int>(value1, value2);
+ // CHECK-FIXES: value2 = std::min(value1, value2);
if (value1 < value2)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min<int>(value2, value1);
+ // CHECK-FIXES: value2 = std::min(value2, value1);
if (value2 > value1)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max
- // CHECK-FIXES: value1 = std::max<int>(value2, value1);
+ // CHECK-FIXES: value1 = std::max(value2, value1);
if (value2 > value1)
value1 = value2;
@@ -56,57 +56,57 @@ void foo() {
value1=value4;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value3 = std::min<int>(value1+value2, value3);
+ // CHECK-FIXES: value3 = std::min(value1+value2, value3);
if(value1+value2<value3)
value3 = value1+value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max<int>(value1, myConstexprMin(value2, value3));
+ // CHECK-FIXES: value1 = std::max(value1, myConstexprMin(value2, value3));
if (value1 < myConstexprMin(value2, value3))
value1 = myConstexprMin(value2, value3);
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::min<int>(value1, myConstexprMax(value2, value3));
+ // CHECK-FIXES: value1 = std::min(value1, myConstexprMax(value2, value3));
if (value1 > myConstexprMax(value2, value3))
value1 = myConstexprMax(value2, value3);
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min<int>(value1, value2);
+ // CHECK-FIXES: value2 = std::min(value1, value2);
if (value1 <= value2)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max<int>(value1, value2);
+ // CHECK-FIXES: value1 = std::max(value1, value2);
if (value1 <= value2)
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max<int>(value2, value1);
+ // CHECK-FIXES: value1 = std::max(value2, value1);
if (value2 >= value1)
value1 = value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: value2 = std::min<int>(value2, value1);
+ // CHECK-FIXES: value2 = std::min(value2, value1);
if (value2 >= value1)
value2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member1 = std::max<int>(obj.member1, obj.member2);
+ // CHECK-FIXES: obj.member1 = std::max(obj.member1, obj.member2);
if (obj.member1 < obj.member2)
obj.member1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min<int>(obj.member1, obj.member2);
+ // CHECK-FIXES: obj.member2 = std::min(obj.member1, obj.member2);
if (obj.member1 < obj.member2)
obj.member2 = obj.member1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min<int>(obj.member2, obj.member1);
+ // CHECK-FIXES: obj.member2 = std::min(obj.member2, obj.member1);
if (obj.member2 > obj.member1)
obj.member2 = obj.member1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member1 = std::max<int>(obj.member2, obj.member1);
+ // CHECK-FIXES: obj.member1 = std::max(obj.member2, obj.member1);
if (obj.member2 > obj.member1)
obj.member1 = obj.member2;
@@ -116,27 +116,27 @@ void foo() {
obj.member1 = value4;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value3 = std::min<int>(obj.member1 + value2, value3);
+ // CHECK-FIXES: value3 = std::min(obj.member1 + value2, value3);
if (obj.member1 + value2 < value3)
value3 = obj.member1 + value2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min<int>(value1, obj.member2);
+ // CHECK-FIXES: obj.member2 = std::min(value1, obj.member2);
if (value1 <= obj.member2)
obj.member2 = value1;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max<int>(value1, obj.member2);
+ // CHECK-FIXES: value1 = std::max(value1, obj.member2);
if (value1 <= obj.member2)
value1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: value1 = std::max<int>(obj.member2, value1);
+ // CHECK-FIXES: value1 = std::max(obj.member2, value1);
if (obj.member2 >= value1)
value1 = obj.member2;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `>=` [readability-use-std-min-max]
- // CHECK-FIXES: obj.member2 = std::min<int>(obj.member2, value1);
+ // CHECK-FIXES: obj.member2 = std::min(obj.member2, value1);
if (obj.member2 >= value1)
obj.member2 = value1;
>From 6acf645970379656373f997a37583cce1ae5e254 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 21 Jan 2024 21:32:46 +0530
Subject: [PATCH 28/47] formatted the code
Signed-off-by: 11happy <soni5happy at gmail.com>
---
clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 6e39ebeda2b2c..4cd7898efb82a 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -90,7 +90,6 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
CondRhsStr + ");")
.str();
}
-
};
const auto OperatorStr = BinaryOp->getOpcodeStr();
if (((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) &&
>From 0eb4aca8023104d228427205e762680737d7b412 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 22 Jan 2024 03:23:27 +0530
Subject: [PATCH 29/47] extra checks
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/readability/UseStdMinMaxCheck.cpp | 2 +-
.../checkers/readability/use-std-min-max.cpp | 14 ++++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 4cd7898efb82a..142425f90e234 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -30,7 +30,7 @@ void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- ifStmt(
+ ifStmt(unless(hasAncestor(ifStmt())),
hasCondition(binaryOperator(hasAnyOperatorName("<", ">", "<=", ">="),
hasLHS(expr().bind("CondLhs")),
hasRHS(expr().bind("CondRhs")))),
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index cdb169fd42c6f..97b9b9924700b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -172,4 +172,18 @@ void foo() {
// No suggestion needed here
MY_IF_MACRO(value1 < value2, value1 = value2;)
+
+ // No suggestion needed here
+ if(value1<value2){
+ value1 = value2;
+ }
+ else if(value1>value2){
+ value2 = value1;
+ }
+
+ // No suggestions needed here
+ if(value1 == value2){
+ if(value1<value3)
+ value1 = value3;
+ }
}
\ No newline at end of file
>From d5b8dc25598b516d81f6ab49c916f2fd41ade6ca Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 22 Jan 2024 16:13:59 +0530
Subject: [PATCH 30/47] ensure if has no else if
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 12 ++++++++----
.../checkers/readability/use-std-min-max.cpp | 17 ++++++++++++++++-
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 142425f90e234..1bc09d8563602 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -30,7 +30,8 @@ void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
- ifStmt(unless(hasAncestor(ifStmt())),
+ ifStmt(
+ stmt().bind("if"),
hasCondition(binaryOperator(hasAnyOperatorName("<", ">", "<=", ">="),
hasLHS(expr().bind("CondLhs")),
hasRHS(expr().bind("CondRhs")))),
@@ -41,8 +42,9 @@ void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
has(binaryOperator(
hasOperatorName("="),
hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs"))))))))
- .bind("if"),
+ hasRHS(expr().bind("AssignRhs"))))))),
+ hasParent(stmt(unless(ifStmt(hasElse(
+ equalsBoundNode("if"))))))), // Ensure `if` has no `else if`
this);
}
@@ -63,12 +65,14 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager &Source = Context.getSourceManager();
const auto *BinaryOp = dyn_cast<BinaryOperator>(If->getCond());
- if (!BinaryOp || If->hasElseStorage())
+ // Ignore `if` statements with `else`
+ if (If->hasElseStorage())
return;
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
+ // Ignore Macros
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 97b9b9924700b..4f36b1dedcbd4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -181,9 +181,24 @@ void foo() {
value2 = value1;
}
- // No suggestions needed here
+ // CHECK-MESSAGES: :[[@LINE+3]]:5: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max(value1, value3);
if(value1 == value2){
if(value1<value3)
value1 = value3;
}
+
+ // CHECK-MESSAGES: :[[@LINE+5]]:7: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value1 = std::max<int>(value1, value4);
+ if(value1 == value2){
+ if(value2 == value3){
+ value3+=1;
+ if(value1<value4){
+ value1 = value4;
+ }
+ }
+ else if(value3>value2){
+ value2 = value3;
+ }
+ }
}
\ No newline at end of file
>From a92160ca6cb61f384609c7dd894bd78821c99921 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 22 Jan 2024 23:51:27 +0530
Subject: [PATCH 31/47] correct style issue
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 61 ++++++++--------
.../checks/readability/use-std-min-max.rst | 69 ++++++++++---------
2 files changed, 64 insertions(+), 66 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 1bc09d8563602..a220ad36df271 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -29,20 +29,21 @@ void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
}
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
+ auto AssignOperator =
+ binaryOperator(hasOperatorName("="), hasLHS(expr().bind("AssignLhs")),
+ hasRHS(expr().bind("AssignRhs")));
+
Finder->addMatcher(
ifStmt(
stmt().bind("if"),
+ unless(hasElse(stmt())), // Ensure `if` has no `else`
hasCondition(binaryOperator(hasAnyOperatorName("<", ">", "<=", ">="),
hasLHS(expr().bind("CondLhs")),
- hasRHS(expr().bind("CondRhs")))),
- hasThen(anyOf(stmt(binaryOperator(hasOperatorName("="),
- hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs")))),
- compoundStmt(statementCountIs(1),
- has(binaryOperator(
- hasOperatorName("="),
- hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs"))))))),
+ hasRHS(expr().bind("CondRhs")))
+ .bind("binaryOp")),
+ hasThen(
+ anyOf(stmt(AssignOperator),
+ compoundStmt(statementCountIs(1), has(AssignOperator)))),
hasParent(stmt(unless(ifStmt(hasElse(
equalsBoundNode("if"))))))), // Ensure `if` has no `else if`
this);
@@ -55,20 +56,11 @@ void UseStdMinMaxCheck::registerPPCallbacks(const SourceManager &SM,
}
void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *CondLhs = Result.Nodes.getNodeAs<Expr>("CondLhs");
- const auto *CondRhs = Result.Nodes.getNodeAs<Expr>("CondRhs");
- const auto *AssignLhs = Result.Nodes.getNodeAs<Expr>("AssignLhs");
- const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
const auto &Context = *Result.Context;
const auto &LO = Context.getLangOpts();
const SourceManager &Source = Context.getSourceManager();
- const auto *BinaryOp = dyn_cast<BinaryOperator>(If->getCond());
- // Ignore `if` statements with `else`
- if (If->hasElseStorage())
- return;
-
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
@@ -76,6 +68,11 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
+ const auto *CondLhs = Result.Nodes.getNodeAs<Expr>("CondLhs");
+ const auto *CondRhs = Result.Nodes.getNodeAs<Expr>("CondRhs");
+ const auto *AssignLhs = Result.Nodes.getNodeAs<Expr>("AssignLhs");
+ const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
+
const auto CreateReplacement = [&](bool UseMax) {
const auto *FunctionName = UseMax ? "std::max" : "std::min";
const auto CondLhsStr = Lexer::getSourceText(
@@ -84,22 +81,20 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
const auto AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- if (CondLhs->getType() != CondRhs->getType()) {
- return (AssignLhsStr + " = " + FunctionName + "<" +
- AssignLhs->getType().getAsString() + ">(" + CondLhsStr + ", " +
- CondRhsStr + ");")
- .str();
- } else {
- return (AssignLhsStr + " = " + FunctionName + "(" + CondLhsStr + ", " +
- CondRhsStr + ");")
- .str();
- }
+ return (AssignLhsStr + " = " + FunctionName +
+ ((CondLhs->getType() != CondRhs->getType())
+ ? "<" + AssignLhs->getType().getAsString() + ">("
+ : "(") +
+ CondLhsStr + ", " + CondRhsStr + ");")
+ .str();
};
+ const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("binaryOp");
+ const auto BinaryOpcode = BinaryOp->getOpcode();
const auto OperatorStr = BinaryOp->getOpcodeStr();
- if (((BinaryOp->getOpcode() == BO_LT || BinaryOp->getOpcode() == BO_LE) &&
+ if (((BinaryOpcode == BO_LT || BinaryOpcode == BO_LE) &&
(tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) ||
- ((BinaryOp->getOpcode() == BO_GT || BinaryOp->getOpcode() == BO_GE) &&
+ ((BinaryOpcode == BO_GT || BinaryOpcode == BO_GE) &&
(tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))) {
diag(IfLocation, "use `std::min` instead of `%0`")
@@ -111,14 +106,12 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
- } else if (((BinaryOp->getOpcode() == BO_LT ||
- BinaryOp->getOpcode() == BO_LE) &&
+ } else if (((BinaryOpcode == BO_LT || BinaryOpcode == BO_LE) &&
(tidy::utils::areStatementsIdentical(CondLhs, AssignLhs,
Context) &&
tidy::utils::areStatementsIdentical(CondRhs, AssignRhs,
Context))) ||
- ((BinaryOp->getOpcode() == BO_GT ||
- BinaryOp->getOpcode() == BO_GE) &&
+ ((BinaryOpcode == BO_GT || BinaryOpcode == BO_GE) &&
(tidy::utils::areStatementsIdentical(CondLhs, AssignRhs,
Context) &&
tidy::utils::areStatementsIdentical(CondRhs, AssignLhs,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index 2cf6a58552cde..5b4ea9fbcbce2 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -1,32 +1,37 @@
-.. title:: clang-tidy - readability-use-std-min-max
-
-readability-use-std-min-max
-===========================
-
-Replaces certain conditional statements with equivalent ``std::min`` or
-``std::max`` expressions. Note: This may impact
-performance in critical code due to potential additional stores compared
-to the original if statement.
-
-
-Examples:
-
-Before:
-
-.. code-block:: c++
-
- void foo() {
- int a = 2, b = 3;
- if (a < b)
- a = b;
- }
-
-
-After:
-
-.. code-block:: c++
-
- void foo() {
- int a = 2, b = 3;
- a = std::max(a, b);
- }
+..title::clang - tidy - readability - use - std - min -
+ max
+
+ readability -
+ use - std - min - max ==
+ == == == == == == == == == == == ==
+ =
+
+ Replaces certain conditional statements with equivalent ``std::min`` or
+``std::max`` expressions
+ .Note
+ : This may impact performance in critical code due to potential additional stores compared to the
+ original if statement
+ .
+
+ Before :
+
+ ..code -
+ block::c++
+
+ void
+ foo() {
+ int a = 2, b = 3;
+ if (a < b)
+ a = b;
+}
+
+After :
+
+ ..code -
+ block::c++
+
+ void
+ foo() {
+ int a = 2, b = 3;
+ a = std::max(a, b);
+}
>From 5eafb596916d8673761101a846f7d22e5c6b2b63 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 23 Jan 2024 00:00:34 +0530
Subject: [PATCH 32/47] correct docs
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../checks/readability/use-std-min-max.rst | 66 ++++++++-----------
1 file changed, 29 insertions(+), 37 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index 5b4ea9fbcbce2..ee8f3c6f0629c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -1,37 +1,29 @@
-..title::clang - tidy - readability - use - std - min -
- max
-
- readability -
- use - std - min - max ==
- == == == == == == == == == == == ==
- =
-
- Replaces certain conditional statements with equivalent ``std::min`` or
-``std::max`` expressions
- .Note
- : This may impact performance in critical code due to potential additional stores compared to the
- original if statement
- .
-
- Before :
-
- ..code -
- block::c++
-
- void
- foo() {
- int a = 2, b = 3;
- if (a < b)
- a = b;
-}
-
-After :
-
- ..code -
- block::c++
-
- void
- foo() {
- int a = 2, b = 3;
- a = std::max(a, b);
-}
+.. title:: clang-tidy - readability-use-std-min-max
+
+readability-use-std-min-max
+===========================
+
+Replaces certain conditional statements with equivalent ``std::min`` or
+``std::max`` expressions. Note: This may impact
+performance in critical code due to potential additional stores compared
+to the original if statement.
+
+Before:
+
+.. code-block:: c++
+
+ void foo() {
+ int a = 2, b = 3;
+ if (a < b)
+ a = b;
+ }
+
+
+After:
+
+.. code-block:: c++
+
+ void foo() {
+ int a = 2, b = 3;
+ a = std::max(a, b);
+ }
>From 26bfbdc2928516d448085022122cfbac13f71c5d Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 23 Jan 2024 00:12:09 +0530
Subject: [PATCH 33/47] correct docs
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/checks/readability/use-std-min-max.rst | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
index ee8f3c6f0629c..73712bdba83b7 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/use-std-min-max.rst
@@ -3,10 +3,10 @@
readability-use-std-min-max
===========================
-Replaces certain conditional statements with equivalent ``std::min`` or
-``std::max`` expressions. Note: This may impact
-performance in critical code due to potential additional stores compared
-to the original if statement.
+Replaces certain conditional statements with equivalent calls to
+``std::min`` or ``std::max``.
+Note: This may impact performance in critical code due to potential
+additional stores compared to the original if statement.
Before:
>From 57bccd6ed654550698bb22100f0919362b1dd7ac Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 23 Jan 2024 01:01:17 +0530
Subject: [PATCH 34/47] static functions
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 116 +++++++++---------
.../readability/UseStdMinMaxCheck.h | 4 +-
clang-tools-extra/docs/ReleaseNotes.rst | 4 +-
3 files changed, 65 insertions(+), 59 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index a220ad36df271..3d115268704c6 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -18,6 +18,45 @@ namespace clang::tidy::readability {
static const llvm::StringRef AlgorithmHeader("<algorithm>");
+static bool MinCondition(const BinaryOperator::Opcode &Op,const Expr *CondLhs,const Expr *CondRhs,const Expr *AssignLhs,const Expr *AssignRhs,const ASTContext &Context){
+ return ((Op == BO_LT || Op == BO_LE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) ||
+ ((Op == BO_GT || Op == BO_GE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)));
+}
+
+static bool MaxCondition(const BinaryOperator::Opcode &Op,const Expr *CondLhs,const Expr *CondRhs,const Expr *AssignLhs,const Expr *AssignRhs,const ASTContext &Context){
+ return ((Op == BO_LT || Op == BO_LE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs,
+ Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs,
+ Context))) ||
+ ((Op == BO_GT || Op == BO_GE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs,
+ Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs,
+ Context)));
+}
+
+static std::string CreateReplacement(const bool UseMax,const BinaryOperator::Opcode &Op,const Expr *CondLhs,const Expr *CondRhs,const Expr *AssignLhs,const ASTContext &Context,const SourceManager &Source,const LangOptions &LO){
+ const auto *FunctionName = UseMax ? "std::max" : "std::min";
+ const auto CondLhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
+ const auto CondRhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
+ const auto AssignLhsStr = Lexer::getSourceText(
+ Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
+ return (AssignLhsStr + " = " + FunctionName +
+ ((CondLhs->getType() != CondRhs->getType())
+ ? "<" + AssignLhs->getType().getAsString() + ">("
+ : "(") +
+ CondLhsStr + ", " + CondRhsStr + ");")
+ .str();
+}
+
+
UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
@@ -59,71 +98,38 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
const auto &Context = *Result.Context;
const auto &LO = Context.getLangOpts();
- const SourceManager &Source = Context.getSourceManager();
-
- const SourceLocation IfLocation = If->getIfLoc();
- const SourceLocation ThenLocation = If->getEndLoc();
-
- // Ignore Macros
- if (IfLocation.isMacroID() || ThenLocation.isMacroID())
- return;
-
const auto *CondLhs = Result.Nodes.getNodeAs<Expr>("CondLhs");
const auto *CondRhs = Result.Nodes.getNodeAs<Expr>("CondRhs");
const auto *AssignLhs = Result.Nodes.getNodeAs<Expr>("AssignLhs");
const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
-
- const auto CreateReplacement = [&](bool UseMax) {
- const auto *FunctionName = UseMax ? "std::max" : "std::min";
- const auto CondLhsStr = Lexer::getSourceText(
- Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
- const auto CondRhsStr = Lexer::getSourceText(
- Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
- const auto AssignLhsStr = Lexer::getSourceText(
- Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- return (AssignLhsStr + " = " + FunctionName +
- ((CondLhs->getType() != CondRhs->getType())
- ? "<" + AssignLhs->getType().getAsString() + ">("
- : "(") +
- CondLhsStr + ", " + CondRhsStr + ");")
- .str();
- };
const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("binaryOp");
const auto BinaryOpcode = BinaryOp->getOpcode();
const auto OperatorStr = BinaryOp->getOpcodeStr();
- if (((BinaryOpcode == BO_LT || BinaryOpcode == BO_LE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) ||
- ((BinaryOpcode == BO_GT || BinaryOpcode == BO_GE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))) {
- diag(IfLocation, "use `std::min` instead of `%0`")
- << OperatorStr
- << FixItHint::CreateReplacement(
- SourceRange(IfLocation, Lexer::getLocForEndOfToken(
- ThenLocation, 0, Source, LO)),
- CreateReplacement(/*UseMax=*/false))
- << IncludeInserter.createIncludeInsertion(
- Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+ const SourceManager &Source = Context.getSourceManager();
+ const SourceLocation IfLocation = If->getIfLoc();
+ const SourceLocation ThenLocation = If->getEndLoc();
- } else if (((BinaryOpcode == BO_LT || BinaryOpcode == BO_LE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs,
- Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignRhs,
- Context))) ||
- ((BinaryOpcode == BO_GT || BinaryOpcode == BO_GE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs,
- Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignLhs,
- Context)))) {
- diag(IfLocation, "use `std::max` instead of `%0`")
+ // Ignore Macros
+ if (IfLocation.isMacroID() || ThenLocation.isMacroID())
+ return;
+
+ auto ReplaceAndDiagnose = [&](bool UseMax) {
+ diag(IfLocation, "use `std::%0` instead of `%1`")
+ << (UseMax ? "max" : "min")
<< OperatorStr
<< FixItHint::CreateReplacement(
- SourceRange(IfLocation, Lexer::getLocForEndOfToken(
- ThenLocation, 0, Source, LO)),
- CreateReplacement(/*UseMax=*/true))
- << IncludeInserter.createIncludeInsertion(
- Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+ SourceRange(IfLocation, Lexer::getLocForEndOfToken(ThenLocation, 0, Source, LO)),
+ CreateReplacement(UseMax, BinaryOpcode, CondLhs, CondRhs,
+ AssignLhs, Context, Source, LO))
+ << IncludeInserter.createIncludeInsertion(Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+ };
+
+
+ if (MinCondition(BinaryOpcode,CondLhs,CondRhs,AssignLhs,AssignRhs,Context)) {
+ ReplaceAndDiagnose(/*UseMax=*/false);
+ }
+ else if (MaxCondition(BinaryOpcode,CondLhs,CondRhs,AssignLhs,AssignRhs,Context)) {
+ ReplaceAndDiagnose(/*UseMax=*/true);
}
}
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
index 860e47794a99c..d5c8da21b3017 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.h
@@ -13,8 +13,8 @@
#include "../utils/IncludeInserter.h"
namespace clang::tidy::readability {
-/// Replaces certain conditional statements with equivalent ``std::min`` or
-/// ``std::max`` expressions.
+/// Replaces certain conditional statements with equivalent calls to
+/// ``std::min`` or ``std::max``.
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/readability/UseStdMinMax.html
class UseStdMinMaxCheck : public ClangTidyCheck {
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e258f4978c45f..89a75cde3e60e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -244,8 +244,8 @@ New checks
- New :doc:`readability-use-std-min-max
<clang-tidy/checks/readability/use-std-min-max>` check.
- Replaces certain conditional statements with equivalent ``std::min`` or
- ``std::max`` expressions.
+ Replaces certain conditional statements with equivalent calls to
+ ``std::min`` or ``std::max``.
New check aliases
^^^^^^^^^^^^^^^^^
>From 61fd66a1c53d66b6087ff4df082e0eeb35e4a162 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 23 Jan 2024 01:14:48 +0530
Subject: [PATCH 35/47] small fix
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 77 +++++++++++--------
1 file changed, 46 insertions(+), 31 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 3d115268704c6..e45dcd4ef78c2 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -18,30 +18,44 @@ namespace clang::tidy::readability {
static const llvm::StringRef AlgorithmHeader("<algorithm>");
-static bool MinCondition(const BinaryOperator::Opcode &Op,const Expr *CondLhs,const Expr *CondRhs,const Expr *AssignLhs,const Expr *AssignRhs,const ASTContext &Context){
- return ((Op == BO_LT || Op == BO_LE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context))) ||
- ((Op == BO_GT || Op == BO_GE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)));
+static bool MinCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
+ const Expr *CondRhs, const Expr *AssignLhs,
+ const Expr *AssignRhs, const ASTContext &Context) {
+ if ((Op == BO_LT || Op == BO_LE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context)))
+ return true;
+
+ if ((Op == BO_GT || Op == BO_GE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))
+ return true;
+
+ return false;
}
-static bool MaxCondition(const BinaryOperator::Opcode &Op,const Expr *CondLhs,const Expr *CondRhs,const Expr *AssignLhs,const Expr *AssignRhs,const ASTContext &Context){
- return ((Op == BO_LT || Op == BO_LE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs,
- Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignRhs,
- Context))) ||
- ((Op == BO_GT || Op == BO_GE) &&
- (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs,
- Context) &&
- tidy::utils::areStatementsIdentical(CondRhs, AssignLhs,
- Context)));
+static bool MaxCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
+ const Expr *CondRhs, const Expr *AssignLhs,
+ const Expr *AssignRhs, const ASTContext &Context) {
+ if ((Op == BO_LT || Op == BO_LE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignLhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignRhs, Context)))
+ return true;
+
+ if ((Op == BO_GT || Op == BO_GE) &&
+ (tidy::utils::areStatementsIdentical(CondLhs, AssignRhs, Context) &&
+ tidy::utils::areStatementsIdentical(CondRhs, AssignLhs, Context)))
+ return true;
+
+ return false;
}
-static std::string CreateReplacement(const bool UseMax,const BinaryOperator::Opcode &Op,const Expr *CondLhs,const Expr *CondRhs,const Expr *AssignLhs,const ASTContext &Context,const SourceManager &Source,const LangOptions &LO){
- const auto *FunctionName = UseMax ? "std::max" : "std::min";
+static std::string
+CreateReplacement(const bool UseMax, const BinaryOperator::Opcode &Op,
+ const Expr *CondLhs, const Expr *CondRhs,
+ const Expr *AssignLhs, const ASTContext &Context,
+ const SourceManager &Source, const LangOptions &LO,
+ const StringRef &FunctionName) {
const auto CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
const auto CondRhsStr = Lexer::getSourceText(
@@ -56,7 +70,6 @@ static std::string CreateReplacement(const bool UseMax,const BinaryOperator::Opc
.str();
}
-
UseStdMinMaxCheck::UseStdMinMaxCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
@@ -112,23 +125,25 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
// Ignore Macros
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
-
+
auto ReplaceAndDiagnose = [&](bool UseMax) {
+ const llvm::StringRef FunctionName = UseMax ? "std::max" : "std::min";
diag(IfLocation, "use `std::%0` instead of `%1`")
- << (UseMax ? "max" : "min")
- << OperatorStr
+ << (UseMax ? "max" : "min") << OperatorStr
<< FixItHint::CreateReplacement(
- SourceRange(IfLocation, Lexer::getLocForEndOfToken(ThenLocation, 0, Source, LO)),
+ SourceRange(IfLocation, Lexer::getLocForEndOfToken(
+ ThenLocation, 0, Source, LO)),
CreateReplacement(UseMax, BinaryOpcode, CondLhs, CondRhs,
- AssignLhs, Context, Source, LO))
- << IncludeInserter.createIncludeInsertion(Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
+ AssignLhs, Context, Source, LO, FunctionName))
+ << IncludeInserter.createIncludeInsertion(
+ Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
-
- if (MinCondition(BinaryOpcode,CondLhs,CondRhs,AssignLhs,AssignRhs,Context)) {
+ if (MinCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
+ Context)) {
ReplaceAndDiagnose(/*UseMax=*/false);
- }
- else if (MaxCondition(BinaryOpcode,CondLhs,CondRhs,AssignLhs,AssignRhs,Context)) {
+ } else if (MaxCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
+ Context)) {
ReplaceAndDiagnose(/*UseMax=*/true);
}
}
>From a841ebccf3401506cfe4c1b0553c4e94b762b804 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 23 Jan 2024 19:27:24 +0530
Subject: [PATCH 36/47] style issues
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 38 +++++++++----------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index e45dcd4ef78c2..50f4a6f297f86 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -18,7 +18,7 @@ namespace clang::tidy::readability {
static const llvm::StringRef AlgorithmHeader("<algorithm>");
-static bool MinCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
+static bool minCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
const Expr *CondRhs, const Expr *AssignLhs,
const Expr *AssignRhs, const ASTContext &Context) {
if ((Op == BO_LT || Op == BO_LE) &&
@@ -34,7 +34,7 @@ static bool MinCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
return false;
}
-static bool MaxCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
+static bool maxCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
const Expr *CondRhs, const Expr *AssignLhs,
const Expr *AssignRhs, const ASTContext &Context) {
if ((Op == BO_LT || Op == BO_LE) &&
@@ -51,16 +51,15 @@ static bool MaxCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
}
static std::string
-CreateReplacement(const bool UseMax, const BinaryOperator::Opcode &Op,
- const Expr *CondLhs, const Expr *CondRhs,
- const Expr *AssignLhs, const ASTContext &Context,
- const SourceManager &Source, const LangOptions &LO,
- const StringRef &FunctionName) {
- const auto CondLhsStr = Lexer::getSourceText(
+createReplacement(const BinaryOperator::Opcode Op, const Expr *CondLhs,
+ const Expr *CondRhs, const Expr *AssignLhs,
+ const ASTContext &Context, const SourceManager &Source,
+ const LangOptions &LO, StringRef FunctionName) {
+ const llvm::StringRef CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
- const auto CondRhsStr = Lexer::getSourceText(
+ const llvm::StringRef CondRhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
- const auto AssignLhsStr = Lexer::getSourceText(
+ const llvm::StringRef AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
return (AssignLhsStr + " = " + FunctionName +
((CondLhs->getType() != CondRhs->getType())
@@ -126,25 +125,24 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
- auto ReplaceAndDiagnose = [&](bool UseMax) {
- const llvm::StringRef FunctionName = UseMax ? "std::max" : "std::min";
- diag(IfLocation, "use `std::%0` instead of `%1`")
- << (UseMax ? "max" : "min") << OperatorStr
+ auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) {
+ diag(IfLocation, "use `%0` instead of `%1`")
+ << FunctionName << OperatorStr
<< FixItHint::CreateReplacement(
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
ThenLocation, 0, Source, LO)),
- CreateReplacement(UseMax, BinaryOpcode, CondLhs, CondRhs,
- AssignLhs, Context, Source, LO, FunctionName))
+ createReplacement(BinaryOpcode, CondLhs, CondRhs, AssignLhs,
+ Context, Source, LO, FunctionName))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
- if (MinCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
+ if (minCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
Context)) {
- ReplaceAndDiagnose(/*UseMax=*/false);
- } else if (MaxCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
+ ReplaceAndDiagnose("std::min");
+ } else if (maxCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
Context)) {
- ReplaceAndDiagnose(/*UseMax=*/true);
+ ReplaceAndDiagnose("std::max");
}
}
>From 7d2c085cbfc0008b56a04b076917e8b500ab3058 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 23 Jan 2024 19:27:24 +0530
Subject: [PATCH 37/47] corrrect style issue
---
.../readability/UseStdMinMaxCheck.cpp | 38 +++++++++----------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index e45dcd4ef78c2..50f4a6f297f86 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -18,7 +18,7 @@ namespace clang::tidy::readability {
static const llvm::StringRef AlgorithmHeader("<algorithm>");
-static bool MinCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
+static bool minCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
const Expr *CondRhs, const Expr *AssignLhs,
const Expr *AssignRhs, const ASTContext &Context) {
if ((Op == BO_LT || Op == BO_LE) &&
@@ -34,7 +34,7 @@ static bool MinCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
return false;
}
-static bool MaxCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
+static bool maxCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
const Expr *CondRhs, const Expr *AssignLhs,
const Expr *AssignRhs, const ASTContext &Context) {
if ((Op == BO_LT || Op == BO_LE) &&
@@ -51,16 +51,15 @@ static bool MaxCondition(const BinaryOperator::Opcode &Op, const Expr *CondLhs,
}
static std::string
-CreateReplacement(const bool UseMax, const BinaryOperator::Opcode &Op,
- const Expr *CondLhs, const Expr *CondRhs,
- const Expr *AssignLhs, const ASTContext &Context,
- const SourceManager &Source, const LangOptions &LO,
- const StringRef &FunctionName) {
- const auto CondLhsStr = Lexer::getSourceText(
+createReplacement(const BinaryOperator::Opcode Op, const Expr *CondLhs,
+ const Expr *CondRhs, const Expr *AssignLhs,
+ const ASTContext &Context, const SourceManager &Source,
+ const LangOptions &LO, StringRef FunctionName) {
+ const llvm::StringRef CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
- const auto CondRhsStr = Lexer::getSourceText(
+ const llvm::StringRef CondRhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
- const auto AssignLhsStr = Lexer::getSourceText(
+ const llvm::StringRef AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
return (AssignLhsStr + " = " + FunctionName +
((CondLhs->getType() != CondRhs->getType())
@@ -126,25 +125,24 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
- auto ReplaceAndDiagnose = [&](bool UseMax) {
- const llvm::StringRef FunctionName = UseMax ? "std::max" : "std::min";
- diag(IfLocation, "use `std::%0` instead of `%1`")
- << (UseMax ? "max" : "min") << OperatorStr
+ auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) {
+ diag(IfLocation, "use `%0` instead of `%1`")
+ << FunctionName << OperatorStr
<< FixItHint::CreateReplacement(
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
ThenLocation, 0, Source, LO)),
- CreateReplacement(UseMax, BinaryOpcode, CondLhs, CondRhs,
- AssignLhs, Context, Source, LO, FunctionName))
+ createReplacement(BinaryOpcode, CondLhs, CondRhs, AssignLhs,
+ Context, Source, LO, FunctionName))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
- if (MinCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
+ if (minCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
Context)) {
- ReplaceAndDiagnose(/*UseMax=*/false);
- } else if (MaxCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
+ ReplaceAndDiagnose("std::min");
+ } else if (maxCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
Context)) {
- ReplaceAndDiagnose(/*UseMax=*/true);
+ ReplaceAndDiagnose("std::max");
}
}
>From abec9b5fa5febad1d169450d74f44dc5b82d9fc5 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 26 Jan 2024 06:41:25 +0530
Subject: [PATCH 38/47] correct functional bugs
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 46 +++++++++++++++++--
.../checkers/readability/use-std-min-max.cpp | 12 ++++-
2 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 50f4a6f297f86..4f9cef7127b70 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -9,13 +9,44 @@
#include "UseStdMinMaxCheck.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Preprocessor.h"
+#include <iostream>
+using namespace std;
using namespace clang::ast_matchers;
namespace clang::tidy::readability {
+class ExprVisitor : public clang::RecursiveASTVisitor<ExprVisitor> {
+public:
+ explicit ExprVisitor(clang::ASTContext *Context) : Context(Context) {}
+ bool visitStmt(const clang::Stmt *S, bool &found,
+ clang::QualType &GlobalImplicitCastType) {
+
+ if (isa<clang::ImplicitCastExpr>(S) && !found) {
+ found = true;
+ const clang::ImplicitCastExpr *ImplicitCast =
+ cast<clang::ImplicitCastExpr>(S);
+ GlobalImplicitCastType = ImplicitCast->getType();
+ // Stop visiting children.
+ return false;
+ }
+ // Continue visiting children.
+ for (const clang::Stmt *Child : S->children()) {
+ if (Child) {
+ this->visitStmt(Child, found, GlobalImplicitCastType);
+ }
+ }
+
+ return true; // Continue visiting other nodes.
+ }
+
+private:
+ clang::ASTContext *Context;
+};
+
static const llvm::StringRef AlgorithmHeader("<algorithm>");
static bool minCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
@@ -54,16 +85,19 @@ static std::string
createReplacement(const BinaryOperator::Opcode Op, const Expr *CondLhs,
const Expr *CondRhs, const Expr *AssignLhs,
const ASTContext &Context, const SourceManager &Source,
- const LangOptions &LO, StringRef FunctionName) {
+ const LangOptions &LO, StringRef FunctionName,
+ QualType GlobalImplicitCastType) {
const llvm::StringRef CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
const llvm::StringRef CondRhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondRhs->getSourceRange()), Source, LO);
const llvm::StringRef AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
+
return (AssignLhsStr + " = " + FunctionName +
((CondLhs->getType() != CondRhs->getType())
- ? "<" + AssignLhs->getType().getAsString() + ">("
+ ? "<" + GlobalImplicitCastType.getCanonicalType().getAsString() +
+ ">("
: "(") +
CondLhsStr + ", " + CondRhsStr + ");")
.str();
@@ -120,6 +154,11 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager &Source = Context.getSourceManager();
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
+ bool found = false;
+ clang::QualType GlobalImplicitCastType;
+
+ ExprVisitor Visitor(Result.Context);
+ Visitor.visitStmt(If, found, GlobalImplicitCastType);
// Ignore Macros
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
@@ -132,7 +171,8 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
ThenLocation, 0, Source, LO)),
createReplacement(BinaryOpcode, CondLhs, CondRhs, AssignLhs,
- Context, Source, LO, FunctionName))
+ Context, Source, LO, FunctionName,
+ GlobalImplicitCastType))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 4f36b1dedcbd4..ebf3a072c9269 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -1,5 +1,4 @@
// RUN: %check_clang_tidy %s readability-use-std-min-max %t
-
#define MY_MACRO_MIN(a, b) ((a) < (b) ? (a) : (b))
constexpr int myConstexprMin(int a, int b) {
@@ -24,8 +23,11 @@ class MyClass {
void foo() {
int value1,value2,value3;
short value4;
+ unsigned int value5;
+ unsigned char value6;
MyClass obj;
+
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
// CHECK-FIXES: value1 = std::max(value1, value2);
if (value1 < value2)
@@ -145,7 +147,7 @@ void foo() {
value3 = MY_MACRO_MIN(value1, value2);
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
- // CHECK-FIXES: value4 = std::max<short>(value4, value2);
+ // CHECK-FIXES: value4 = std::max<int>(value4, value2);
if (value4 < value2){
value4 = value2;
}
@@ -201,4 +203,10 @@ void foo() {
value2 = value3;
}
}
+
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value6 = std::min<unsigned int>(value5, value6);
+ if(value5<value6){
+ value6 = value5;
+ }
}
\ No newline at end of file
>From 6a0e495888c6d81061146ded25bd4d3978fd1086 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 26 Jan 2024 13:57:20 +0530
Subject: [PATCH 39/47] pass dependent types
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 12 +++++++---
.../checkers/readability/use-std-min-max.cpp | 23 +++++++++++++++++--
2 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 4f9cef7127b70..879d39a6f3061 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -95,7 +95,8 @@ createReplacement(const BinaryOperator::Opcode Op, const Expr *CondLhs,
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
return (AssignLhsStr + " = " + FunctionName +
- ((CondLhs->getType() != CondRhs->getType())
+ ((CondLhs->getType()->getUnqualifiedDesugaredType() !=
+ CondRhs->getType()->getUnqualifiedDesugaredType())
? "<" + GlobalImplicitCastType.getCanonicalType().getAsString() +
">("
: "(") +
@@ -154,16 +155,21 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager &Source = Context.getSourceManager();
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
- bool found = false;
+ bool Found = false;
clang::QualType GlobalImplicitCastType;
ExprVisitor Visitor(Result.Context);
- Visitor.visitStmt(If, found, GlobalImplicitCastType);
+ Visitor.visitStmt(If, Found, GlobalImplicitCastType);
// Ignore Macros
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
return;
+ // Ignore Dependent types
+ if (CondLhs->getType()->isDependentType() ||
+ CondRhs->getType()->isDependentType())
+ return;
+
auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) {
diag(IfLocation, "use `%0` instead of `%1`")
<< FunctionName << OperatorStr
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index ebf3a072c9269..638e26ef8c25f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -20,11 +20,15 @@ class MyClass {
int member2;
};
-void foo() {
+template<typename T>
+
+void foo(T value7) {
int value1,value2,value3;
short value4;
unsigned int value5;
unsigned char value6;
+ const int value8 = 5;
+ volatile int value9 = 6;
MyClass obj;
@@ -209,4 +213,19 @@ void foo() {
if(value5<value6){
value6 = value5;
}
-}
\ No newline at end of file
+
+ //No suggestion needed here
+ if(value7<value6){
+ value6 = value7;
+ }
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ //CHECK-FIXES: value1 = std::min(value8, value1);
+ if(value8<value1)
+ value1 = value8;
+
+ //CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ //CHECK-FIXES: value1 = std::min(value9, value1);
+ if(value9<value1)
+ value1 = value9;
+}
>From 274b55fdfd464afef20befa3feed55869a087221 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Fri, 26 Jan 2024 21:52:32 +0530
Subject: [PATCH 40/47] filter implicit cast expr
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 59 ++++++++++++++++---
1 file changed, 51 insertions(+), 8 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 879d39a6f3061..a904097dd5144 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -12,13 +12,53 @@
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Preprocessor.h"
-#include <iostream>
-using namespace std;
using namespace clang::ast_matchers;
namespace clang::tidy::readability {
+static bool isImplicitCastType(const clang::CastKind castKind) {
+ switch (castKind) {
+ case clang::CK_CPointerToObjCPointerCast:
+ case clang::CK_BlockPointerToObjCPointerCast:
+ case clang::CK_BitCast:
+ case clang::CK_AnyPointerToBlockPointerCast:
+ case clang::CK_NullToMemberPointer:
+ case clang::CK_NullToPointer:
+ case clang::CK_IntegralToPointer:
+ case clang::CK_PointerToIntegral:
+ case clang::CK_IntegralCast:
+ case clang::CK_BooleanToSignedIntegral:
+ case clang::CK_IntegralToFloating:
+ case clang::CK_FloatingToIntegral:
+ case clang::CK_FloatingCast:
+ case clang::CK_ObjCObjectLValueCast:
+ case clang::CK_FloatingRealToComplex:
+ case clang::CK_FloatingComplexToReal:
+ case clang::CK_FloatingComplexCast:
+ case clang::CK_FloatingComplexToIntegralComplex:
+ case clang::CK_IntegralRealToComplex:
+ case clang::CK_IntegralComplexToReal:
+ case clang::CK_IntegralComplexCast:
+ case clang::CK_IntegralComplexToFloatingComplex:
+ case clang::CK_FloatingToFixedPoint:
+ case clang::CK_FixedPointToFloating:
+ case clang::CK_FixedPointCast:
+ case clang::CK_FixedPointToIntegral:
+ case clang::CK_IntegralToFixedPoint:
+ case clang::CK_MatrixCast:
+ case clang::CK_PointerToBoolean:
+ case clang::CK_IntegralToBoolean:
+ case clang::CK_FloatingToBoolean:
+ case clang::CK_MemberPointerToBoolean:
+ case clang::CK_FloatingComplexToBoolean:
+ case clang::CK_IntegralComplexToBoolean:
+ return true;
+ default:
+ return false;
+ }
+}
+
class ExprVisitor : public clang::RecursiveASTVisitor<ExprVisitor> {
public:
explicit ExprVisitor(clang::ASTContext *Context) : Context(Context) {}
@@ -26,12 +66,15 @@ class ExprVisitor : public clang::RecursiveASTVisitor<ExprVisitor> {
clang::QualType &GlobalImplicitCastType) {
if (isa<clang::ImplicitCastExpr>(S) && !found) {
- found = true;
- const clang::ImplicitCastExpr *ImplicitCast =
- cast<clang::ImplicitCastExpr>(S);
- GlobalImplicitCastType = ImplicitCast->getType();
- // Stop visiting children.
- return false;
+ const auto CastKind = cast<clang::ImplicitCastExpr>(S)->getCastKind();
+ if (isImplicitCastType(CastKind)) {
+ found = true;
+ const clang::ImplicitCastExpr *ImplicitCast =
+ cast<clang::ImplicitCastExpr>(S);
+ GlobalImplicitCastType = ImplicitCast->getType();
+ // Stop visiting children.
+ return false;
+ }
}
// Continue visiting children.
for (const clang::Stmt *Child : S->children()) {
>From 8bf8235b7e7ef90649c4ae815019565fcc1726f2 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sat, 27 Jan 2024 23:52:03 +0530
Subject: [PATCH 41/47] Add mising type, optimise
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 32 +++++++++++++------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index a904097dd5144..11cacade5623c 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -53,6 +53,7 @@ static bool isImplicitCastType(const clang::CastKind castKind) {
case clang::CK_MemberPointerToBoolean:
case clang::CK_FloatingComplexToBoolean:
case clang::CK_IntegralComplexToBoolean:
+ case clang::CK_UserDefinedConversion:
return true;
default:
return false;
@@ -124,12 +125,13 @@ static bool maxCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
return false;
}
-static std::string
-createReplacement(const BinaryOperator::Opcode Op, const Expr *CondLhs,
- const Expr *CondRhs, const Expr *AssignLhs,
- const ASTContext &Context, const SourceManager &Source,
- const LangOptions &LO, StringRef FunctionName,
- QualType GlobalImplicitCastType) {
+static std::string createReplacement(const BinaryOperator::Opcode Op,
+ const Expr *CondLhs, const Expr *CondRhs,
+ const Expr *AssignLhs,
+ const ASTContext *Context,
+ const SourceManager &Source,
+ const LangOptions &LO,
+ StringRef FunctionName, const IfStmt *If) {
const llvm::StringRef CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
const llvm::StringRef CondRhsStr = Lexer::getSourceText(
@@ -137,9 +139,20 @@ createReplacement(const BinaryOperator::Opcode Op, const Expr *CondLhs,
const llvm::StringRef AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
+ bool IsImplicitCastTypeNeeded = false;
+ clang::QualType GlobalImplicitCastType;
+ if ((CondLhs->getType()->getUnqualifiedDesugaredType() !=
+ CondRhs->getType()->getUnqualifiedDesugaredType()) &&
+ (CondLhs->getType().getCanonicalType() !=
+ (CondRhs->getType().getCanonicalType()))) {
+ IsImplicitCastTypeNeeded = true;
+ bool Found = false;
+ ExprVisitor Visitor(const_cast<ASTContext *>(Context));
+ Visitor.visitStmt(If, Found, GlobalImplicitCastType);
+ }
+
return (AssignLhsStr + " = " + FunctionName +
- ((CondLhs->getType()->getUnqualifiedDesugaredType() !=
- CondRhs->getType()->getUnqualifiedDesugaredType())
+ (IsImplicitCastTypeNeeded
? "<" + GlobalImplicitCastType.getCanonicalType().getAsString() +
">("
: "(") +
@@ -220,8 +233,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
ThenLocation, 0, Source, LO)),
createReplacement(BinaryOpcode, CondLhs, CondRhs, AssignLhs,
- Context, Source, LO, FunctionName,
- GlobalImplicitCastType))
+ Result.Context, Source, LO, FunctionName, If))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
>From d8df8c8202d7c29d9a14eff4a96ef1ab43d088f3 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 28 Jan 2024 00:09:27 +0530
Subject: [PATCH 42/47] removed whitespace
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../test/clang-tidy/checkers/readability/use-std-min-max.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 638e26ef8c25f..b8a1dbd0c7661 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -31,7 +31,6 @@ void foo(T value7) {
volatile int value9 = 6;
MyClass obj;
-
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
// CHECK-FIXES: value1 = std::max(value1, value2);
if (value1 < value2)
>From 8a5d58515096b6131d8c174f8744c17e87567522 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 28 Jan 2024 01:23:08 +0530
Subject: [PATCH 43/47] remove unsed initialisation
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../clang-tidy/readability/UseStdMinMaxCheck.cpp | 14 ++------------
1 file changed, 2 insertions(+), 12 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 11cacade5623c..ea9dd0309dceb 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -62,7 +62,6 @@ static bool isImplicitCastType(const clang::CastKind castKind) {
class ExprVisitor : public clang::RecursiveASTVisitor<ExprVisitor> {
public:
- explicit ExprVisitor(clang::ASTContext *Context) : Context(Context) {}
bool visitStmt(const clang::Stmt *S, bool &found,
clang::QualType &GlobalImplicitCastType) {
@@ -86,9 +85,6 @@ class ExprVisitor : public clang::RecursiveASTVisitor<ExprVisitor> {
return true; // Continue visiting other nodes.
}
-
-private:
- clang::ASTContext *Context;
};
static const llvm::StringRef AlgorithmHeader("<algorithm>");
@@ -128,7 +124,6 @@ static bool maxCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
static std::string createReplacement(const BinaryOperator::Opcode Op,
const Expr *CondLhs, const Expr *CondRhs,
const Expr *AssignLhs,
- const ASTContext *Context,
const SourceManager &Source,
const LangOptions &LO,
StringRef FunctionName, const IfStmt *If) {
@@ -147,7 +142,7 @@ static std::string createReplacement(const BinaryOperator::Opcode Op,
(CondRhs->getType().getCanonicalType()))) {
IsImplicitCastTypeNeeded = true;
bool Found = false;
- ExprVisitor Visitor(const_cast<ASTContext *>(Context));
+ ExprVisitor Visitor;
Visitor.visitStmt(If, Found, GlobalImplicitCastType);
}
@@ -211,11 +206,6 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const SourceManager &Source = Context.getSourceManager();
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
- bool Found = false;
- clang::QualType GlobalImplicitCastType;
-
- ExprVisitor Visitor(Result.Context);
- Visitor.visitStmt(If, Found, GlobalImplicitCastType);
// Ignore Macros
if (IfLocation.isMacroID() || ThenLocation.isMacroID())
@@ -233,7 +223,7 @@ void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
ThenLocation, 0, Source, LO)),
createReplacement(BinaryOpcode, CondLhs, CondRhs, AssignLhs,
- Result.Context, Source, LO, FunctionName, If))
+ Source, LO, FunctionName, If))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
>From 85fb67d6d673602b0cdcc78dabd2db7f9b9bee6c Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Sun, 28 Jan 2024 02:31:59 +0530
Subject: [PATCH 44/47] small change
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../test/clang-tidy/checkers/readability/use-std-min-max.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index b8a1dbd0c7661..a9633b087d42f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -12,7 +12,7 @@ constexpr int myConstexprMax(int a, int b) {
#define MY_IF_MACRO(condition, statement) \
if (condition) { \
statement \
- }
+ } \
class MyClass {
public:
@@ -46,7 +46,7 @@ void foo(T value7) {
if (value2 > value1)
value2 = value1;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
// CHECK-FIXES: value1 = std::max(value2, value1);
if (value2 > value1)
value1 = value2;
>From 1214547f9980714cfdc6f8e9565f3b3cc17cc3fb Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Mon, 29 Jan 2024 06:16:35 +0530
Subject: [PATCH 45/47] simplify
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 158 +++++-------------
.../checkers/readability/use-std-min-max.cpp | 30 ++--
2 files changed, 58 insertions(+), 130 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index ea9dd0309dceb..78886665c1134 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -9,7 +9,6 @@
#include "UseStdMinMaxCheck.h"
#include "../utils/ASTUtils.h"
#include "clang/AST/ASTContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Preprocessor.h"
@@ -17,76 +16,6 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
-static bool isImplicitCastType(const clang::CastKind castKind) {
- switch (castKind) {
- case clang::CK_CPointerToObjCPointerCast:
- case clang::CK_BlockPointerToObjCPointerCast:
- case clang::CK_BitCast:
- case clang::CK_AnyPointerToBlockPointerCast:
- case clang::CK_NullToMemberPointer:
- case clang::CK_NullToPointer:
- case clang::CK_IntegralToPointer:
- case clang::CK_PointerToIntegral:
- case clang::CK_IntegralCast:
- case clang::CK_BooleanToSignedIntegral:
- case clang::CK_IntegralToFloating:
- case clang::CK_FloatingToIntegral:
- case clang::CK_FloatingCast:
- case clang::CK_ObjCObjectLValueCast:
- case clang::CK_FloatingRealToComplex:
- case clang::CK_FloatingComplexToReal:
- case clang::CK_FloatingComplexCast:
- case clang::CK_FloatingComplexToIntegralComplex:
- case clang::CK_IntegralRealToComplex:
- case clang::CK_IntegralComplexToReal:
- case clang::CK_IntegralComplexCast:
- case clang::CK_IntegralComplexToFloatingComplex:
- case clang::CK_FloatingToFixedPoint:
- case clang::CK_FixedPointToFloating:
- case clang::CK_FixedPointCast:
- case clang::CK_FixedPointToIntegral:
- case clang::CK_IntegralToFixedPoint:
- case clang::CK_MatrixCast:
- case clang::CK_PointerToBoolean:
- case clang::CK_IntegralToBoolean:
- case clang::CK_FloatingToBoolean:
- case clang::CK_MemberPointerToBoolean:
- case clang::CK_FloatingComplexToBoolean:
- case clang::CK_IntegralComplexToBoolean:
- case clang::CK_UserDefinedConversion:
- return true;
- default:
- return false;
- }
-}
-
-class ExprVisitor : public clang::RecursiveASTVisitor<ExprVisitor> {
-public:
- bool visitStmt(const clang::Stmt *S, bool &found,
- clang::QualType &GlobalImplicitCastType) {
-
- if (isa<clang::ImplicitCastExpr>(S) && !found) {
- const auto CastKind = cast<clang::ImplicitCastExpr>(S)->getCastKind();
- if (isImplicitCastType(CastKind)) {
- found = true;
- const clang::ImplicitCastExpr *ImplicitCast =
- cast<clang::ImplicitCastExpr>(S);
- GlobalImplicitCastType = ImplicitCast->getType();
- // Stop visiting children.
- return false;
- }
- }
- // Continue visiting children.
- for (const clang::Stmt *Child : S->children()) {
- if (Child) {
- this->visitStmt(Child, found, GlobalImplicitCastType);
- }
- }
-
- return true; // Continue visiting other nodes.
- }
-};
-
static const llvm::StringRef AlgorithmHeader("<algorithm>");
static bool minCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
@@ -121,12 +50,12 @@ static bool maxCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
return false;
}
-static std::string createReplacement(const BinaryOperator::Opcode Op,
- const Expr *CondLhs, const Expr *CondRhs,
+static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
const Expr *AssignLhs,
const SourceManager &Source,
const LangOptions &LO,
- StringRef FunctionName, const IfStmt *If) {
+ StringRef FunctionName,
+ const BinaryOperator *BO) {
const llvm::StringRef CondLhsStr = Lexer::getSourceText(
Source.getExpansionRange(CondLhs->getSourceRange()), Source, LO);
const llvm::StringRef CondRhsStr = Lexer::getSourceText(
@@ -134,20 +63,19 @@ static std::string createReplacement(const BinaryOperator::Opcode Op,
const llvm::StringRef AssignLhsStr = Lexer::getSourceText(
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
- bool IsImplicitCastTypeNeeded = false;
clang::QualType GlobalImplicitCastType;
- if ((CondLhs->getType()->getUnqualifiedDesugaredType() !=
- CondRhs->getType()->getUnqualifiedDesugaredType()) &&
- (CondLhs->getType().getCanonicalType() !=
- (CondRhs->getType().getCanonicalType()))) {
- IsImplicitCastTypeNeeded = true;
- bool Found = false;
- ExprVisitor Visitor;
- Visitor.visitStmt(If, Found, GlobalImplicitCastType);
+ if (CondLhs->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ .getUnqualifiedType() != CondRhs->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ .getUnqualifiedType()) {
+ GlobalImplicitCastType = BO->getLHS()->getType();
}
return (AssignLhsStr + " = " + FunctionName +
- (IsImplicitCastTypeNeeded
+ (!GlobalImplicitCastType.isNull()
? "<" + GlobalImplicitCastType.getCanonicalType().getAsString() +
">("
: "(") +
@@ -165,24 +93,35 @@ void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
}
+// Ignore if statements that are inside macros.
+AST_MATCHER(IfStmt, isIfInMacro) {
+ return Node.getIfLoc().isMacroID() || Node.getEndLoc().isMacroID();
+}
+
+// Ignore expressions that are of dependent types.
+AST_MATCHER(Expr, isExprDependentType) {
+ return Node.getType()->isDependentType();
+}
+
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
auto AssignOperator =
binaryOperator(hasOperatorName("="), hasLHS(expr().bind("AssignLhs")),
hasRHS(expr().bind("AssignRhs")));
-
+ auto BinaryOperator =
+ binaryOperator(
+ hasAnyOperatorName("<", ">", "<=", ">="),
+ hasLHS(expr(unless(isExprDependentType())).bind("CondLhs")),
+ hasRHS(expr(unless(isExprDependentType())).bind("CondRhs")))
+ .bind("binaryOp");
Finder->addMatcher(
- ifStmt(
- stmt().bind("if"),
- unless(hasElse(stmt())), // Ensure `if` has no `else`
- hasCondition(binaryOperator(hasAnyOperatorName("<", ">", "<=", ">="),
- hasLHS(expr().bind("CondLhs")),
- hasRHS(expr().bind("CondRhs")))
- .bind("binaryOp")),
- hasThen(
- anyOf(stmt(AssignOperator),
- compoundStmt(statementCountIs(1), has(AssignOperator)))),
- hasParent(stmt(unless(ifStmt(hasElse(
- equalsBoundNode("if"))))))), // Ensure `if` has no `else if`
+ ifStmt(stmt().bind("if"), unless(isIfInMacro()),
+ unless(hasElse(stmt())), // Ensure `if` has no `else`
+ hasCondition(BinaryOperator),
+ hasThen(
+ anyOf(stmt(AssignOperator),
+ compoundStmt(statementCountIs(1), has(AssignOperator)))),
+ hasParent(stmt(unless(ifStmt(hasElse(
+ equalsBoundNode("if"))))))), // Ensure `if` has no `else if`
this);
}
@@ -194,45 +133,34 @@ void UseStdMinMaxCheck::registerPPCallbacks(const SourceManager &SM,
void UseStdMinMaxCheck::check(const MatchFinder::MatchResult &Result) {
const auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
- const auto &Context = *Result.Context;
- const auto &LO = Context.getLangOpts();
+ const auto &LO = (*Result.Context).getLangOpts();
const auto *CondLhs = Result.Nodes.getNodeAs<Expr>("CondLhs");
const auto *CondRhs = Result.Nodes.getNodeAs<Expr>("CondRhs");
const auto *AssignLhs = Result.Nodes.getNodeAs<Expr>("AssignLhs");
const auto *AssignRhs = Result.Nodes.getNodeAs<Expr>("AssignRhs");
const auto *BinaryOp = Result.Nodes.getNodeAs<BinaryOperator>("binaryOp");
const auto BinaryOpcode = BinaryOp->getOpcode();
- const auto OperatorStr = BinaryOp->getOpcodeStr();
- const SourceManager &Source = Context.getSourceManager();
const SourceLocation IfLocation = If->getIfLoc();
const SourceLocation ThenLocation = If->getEndLoc();
- // Ignore Macros
- if (IfLocation.isMacroID() || ThenLocation.isMacroID())
- return;
-
- // Ignore Dependent types
- if (CondLhs->getType()->isDependentType() ||
- CondRhs->getType()->isDependentType())
- return;
-
auto ReplaceAndDiagnose = [&](const llvm::StringRef FunctionName) {
+ const SourceManager &Source = (*Result.Context).getSourceManager();
diag(IfLocation, "use `%0` instead of `%1`")
- << FunctionName << OperatorStr
+ << FunctionName << BinaryOp->getOpcodeStr()
<< FixItHint::CreateReplacement(
SourceRange(IfLocation, Lexer::getLocForEndOfToken(
ThenLocation, 0, Source, LO)),
- createReplacement(BinaryOpcode, CondLhs, CondRhs, AssignLhs,
- Source, LO, FunctionName, If))
+ createReplacement(CondLhs, CondRhs, AssignLhs, Source, LO,
+ FunctionName, BinaryOp))
<< IncludeInserter.createIncludeInsertion(
Source.getFileID(If->getBeginLoc()), AlgorithmHeader);
};
if (minCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
- Context)) {
+ (*Result.Context))) {
ReplaceAndDiagnose("std::min");
} else if (maxCondition(BinaryOpcode, CondLhs, CondRhs, AssignLhs, AssignRhs,
- Context)) {
+ (*Result.Context))) {
ReplaceAndDiagnose("std::max");
}
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index a9633b087d42f..1029f0b109476 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s readability-use-std-min-max %t
+// RUN: %check_clang_tidy -std=c++11-or-later %s readability-use-std-min-max %t -- -- -fno-delayed-template-parsing
#define MY_MACRO_MIN(a, b) ((a) < (b) ? (a) : (b))
constexpr int myConstexprMin(int a, int b) {
@@ -12,7 +12,7 @@ constexpr int myConstexprMax(int a, int b) {
#define MY_IF_MACRO(condition, statement) \
if (condition) { \
statement \
- } \
+ }
class MyClass {
public:
@@ -24,12 +24,6 @@ template<typename T>
void foo(T value7) {
int value1,value2,value3;
- short value4;
- unsigned int value5;
- unsigned char value6;
- const int value8 = 5;
- volatile int value9 = 6;
- MyClass obj;
// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
// CHECK-FIXES: value1 = std::max(value1, value2);
@@ -54,9 +48,10 @@ void foo(T value7) {
// No suggestion needed here
if (value1 == value2)
value1 = value2;
-
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+
+ // CHECK-MESSAGES: :[[@LINE+3]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
// CHECK-FIXES: value1 = std::max<int>(value1, value4);
+ short value4;
if(value1<value4)
value1=value4;
@@ -95,8 +90,9 @@ void foo(T value7) {
if (value2 >= value1)
value2 = value1;
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-MESSAGES: :[[@LINE+3]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
// CHECK-FIXES: obj.member1 = std::max(obj.member1, obj.member2);
+ MyClass obj;
if (obj.member1 < obj.member2)
obj.member1 = obj.member2;
@@ -206,9 +202,11 @@ void foo(T value7) {
value2 = value3;
}
}
-
- // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+
+ // CHECK-MESSAGES: :[[@LINE+4]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
// CHECK-FIXES: value6 = std::min<unsigned int>(value5, value6);
+ unsigned int value5;
+ unsigned char value6;
if(value5<value6){
value6 = value5;
}
@@ -218,13 +216,15 @@ void foo(T value7) {
value6 = value7;
}
- //CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ //CHECK-MESSAGES: :[[@LINE+3]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
//CHECK-FIXES: value1 = std::min(value8, value1);
+ const int value8 = 5;
if(value8<value1)
value1 = value8;
- //CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
+ //CHECK-MESSAGES: :[[@LINE+3]]:3: warning: use `std::min` instead of `<` [readability-use-std-min-max]
//CHECK-FIXES: value1 = std::min(value9, value1);
+ volatile int value9 = 6;
if(value9<value1)
value1 = value9;
}
>From 6aef7137a8cdc58efaceb296730b71c12c7be46f Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Tue, 30 Jan 2024 14:44:45 +0530
Subject: [PATCH 46/47] small fix
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 47 ++++++++++---------
1 file changed, 24 insertions(+), 23 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 78886665c1134..1ff2863643d68 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -16,6 +16,15 @@ using namespace clang::ast_matchers;
namespace clang::tidy::readability {
+namespace {
+
+// Ignore if statements that are inside macros.
+AST_MATCHER(IfStmt, isIfInMacro) {
+ return Node.getIfLoc().isMacroID() || Node.getEndLoc().isMacroID();
+}
+
+} // namespace
+
static const llvm::StringRef AlgorithmHeader("<algorithm>");
static bool minCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
@@ -64,13 +73,15 @@ static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
Source.getExpansionRange(AssignLhs->getSourceRange()), Source, LO);
clang::QualType GlobalImplicitCastType;
- if (CondLhs->getType()
- .getCanonicalType()
- .getNonReferenceType()
- .getUnqualifiedType() != CondRhs->getType()
- .getCanonicalType()
- .getNonReferenceType()
- .getUnqualifiedType()) {
+ clang::QualType LhsType = CondLhs->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ .getUnqualifiedType();
+ clang::QualType RhsType = CondRhs->getType()
+ .getCanonicalType()
+ .getNonReferenceType()
+ .getUnqualifiedType();
+ if (LhsType != RhsType) {
GlobalImplicitCastType = BO->getLHS()->getType();
}
@@ -93,25 +104,15 @@ void UseStdMinMaxCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", IncludeInserter.getStyle());
}
-// Ignore if statements that are inside macros.
-AST_MATCHER(IfStmt, isIfInMacro) {
- return Node.getIfLoc().isMacroID() || Node.getEndLoc().isMacroID();
-}
-
-// Ignore expressions that are of dependent types.
-AST_MATCHER(Expr, isExprDependentType) {
- return Node.getType()->isDependentType();
-}
-
void UseStdMinMaxCheck::registerMatchers(MatchFinder *Finder) {
auto AssignOperator =
- binaryOperator(hasOperatorName("="), hasLHS(expr().bind("AssignLhs")),
- hasRHS(expr().bind("AssignRhs")));
+ binaryOperator(hasOperatorName("="),
+ hasLHS(expr(unless(isTypeDependent())).bind("AssignLhs")),
+ hasRHS(expr(unless(isTypeDependent())).bind("AssignRhs")));
auto BinaryOperator =
- binaryOperator(
- hasAnyOperatorName("<", ">", "<=", ">="),
- hasLHS(expr(unless(isExprDependentType())).bind("CondLhs")),
- hasRHS(expr(unless(isExprDependentType())).bind("CondRhs")))
+ binaryOperator(hasAnyOperatorName("<", ">", "<=", ">="),
+ hasLHS(expr(unless(isTypeDependent())).bind("CondLhs")),
+ hasRHS(expr(unless(isTypeDependent())).bind("CondRhs")))
.bind("binaryOp");
Finder->addMatcher(
ifStmt(stmt().bind("if"), unless(isIfInMacro()),
>From f03b2ffed122b5b44116202affce993d99552853 Mon Sep 17 00:00:00 2001
From: 11happy <soni5happy at gmail.com>
Date: Thu, 1 Feb 2024 15:44:32 +0530
Subject: [PATCH 47/47] non template alias
Signed-off-by: 11happy <soni5happy at gmail.com>
---
.../readability/UseStdMinMaxCheck.cpp | 25 ++++++++++++++++---
.../checkers/readability/use-std-min-max.cpp | 24 ++++++++++++++++++
2 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
index 1ff2863643d68..e24470e8aab34 100644
--- a/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/UseStdMinMaxCheck.cpp
@@ -59,6 +59,26 @@ static bool maxCondition(const BinaryOperator::Opcode Op, const Expr *CondLhs,
return false;
}
+QualType getNonTemplateAlias(QualType QT) {
+ while (true) {
+ // cast to a TypedefType
+ if (const TypedefType *TT = dyn_cast<TypedefType>(QT)) {
+ // check if the typedef is a template and if it is dependent
+ if (!TT->getDecl()->getDescribedTemplate() &&
+ !TT->getDecl()->getDeclContext()->isDependentContext())
+ return QT;
+ QT = TT->getDecl()->getUnderlyingType();
+ }
+ // cast to elaborated type
+ else if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(QT)) {
+ QT = ET->getNamedType();
+ } else {
+ break;
+ }
+ }
+ return QT;
+}
+
static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
const Expr *AssignLhs,
const SourceManager &Source,
@@ -82,13 +102,12 @@ static std::string createReplacement(const Expr *CondLhs, const Expr *CondRhs,
.getNonReferenceType()
.getUnqualifiedType();
if (LhsType != RhsType) {
- GlobalImplicitCastType = BO->getLHS()->getType();
+ GlobalImplicitCastType = getNonTemplateAlias(BO->getLHS()->getType());
}
return (AssignLhsStr + " = " + FunctionName +
(!GlobalImplicitCastType.isNull()
- ? "<" + GlobalImplicitCastType.getCanonicalType().getAsString() +
- ">("
+ ? "<" + GlobalImplicitCastType.getAsString() + ">("
: "(") +
CondLhsStr + ", " + CondRhsStr + ");")
.str();
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
index 1029f0b109476..9c0e2eabda348 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/use-std-min-max.cpp
@@ -228,3 +228,27 @@ void foo(T value7) {
if(value9<value1)
value1 = value9;
}
+
+using my_size = unsigned long long;
+
+template<typename T>
+struct MyVector
+{
+ using size_type = my_size;
+ size_type size() const;
+};
+
+void testVectorSizeType() {
+ MyVector<int> v;
+ unsigned int value;
+
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `>` [readability-use-std-min-max]
+ // CHECK-FIXES: value = std::max<my_size>(v.size(), value);
+ if (v.size() > value)
+ value = v.size();
+
+ // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: use `std::max` instead of `<` [readability-use-std-min-max]
+ // CHECK-FIXES: value = std::max<my_size>(value, v.size());
+ if (value < v.size())
+ value = v.size();
+}
More information about the llvm-commits
mailing list