[llvm] [clang] [clang-tools-extra] Add clang-tidy check to suggest replacement of conditional statement with std::min/std::max (PR #77816)
Bhuminjay Soni via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 17 03:31:54 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/20] 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 408c822b861c5f..4bc373bb69bb84 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 00000000000000..fba8c68f737450
--- /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 00000000000000..b7eabcc7d16d41
--- /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 0b0aad7c0dcb36..63f8f03be6bb91 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 b4d87e0ed2a67a..c3fb990ad6a738 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 2f86121ad87299..c2eac55425c69e 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 00000000000000..e95858999b2772
--- /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 00000000000000..d29e9aa9fec708
--- /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/20] 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 fba8c68f737450..86420765d6f6c6 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 b7eabcc7d16d41..02ebed83fed6c8 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/20] 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 e95858999b2772..2b75e78ecb8082 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/20] 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 2b75e78ecb8082..e95858999b2772 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/20] 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 86420765d6f6c6..fba8c68f737450 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 02ebed83fed6c8..b7eabcc7d16d41 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/20] 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 4bc373bb69bb84..408c822b861c5f 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 fba8c68f737450..00000000000000
--- 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 b7eabcc7d16d41..00000000000000
--- 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 63f8f03be6bb91..0b0aad7c0dcb36 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 c3fb990ad6a738..b4d87e0ed2a67a 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 c2eac55425c69e..2f86121ad87299 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 e95858999b2772..00000000000000
--- 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 d29e9aa9fec708..00000000000000
--- 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/20] 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 408c822b861c5f..3670a439954345 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 0b0aad7c0dcb36..cba32ea24cec7c 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 00000000000000..984792322ce5d3
--- /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 00000000000000..476b19ba5c9cf9
--- /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 b4d87e0ed2a67a..2d3a2c2981e6ca 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 2f86121ad87299..25b3550a77e463 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 00000000000000..c8b9bdc7c5ea3b
--- /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 00000000000000..37ee1fd65fb915
--- /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/20] 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 984792322ce5d3..f203ec1e89b35e 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/20] 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 2d3a2c2981e6ca..314e0eb69f7934 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/20] 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/20] 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 c8b9bdc7c5ea3b..573beeeb2a842b 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/20] 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 f203ec1e89b35e..1a4392523cf187 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 573beeeb2a842b..2364acacbaffd7 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 37ee1fd65fb915..b65e3a9b27cc21 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/20] 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 2364acacbaffd7..de22f069d21923 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/20] 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 de22f069d21923..0d621d4d4477f2 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 b65e3a9b27cc21..1dc48ffc63cfb5 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/20] 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 0d621d4d4477f2..7e64a05ccd8b89 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 1dc48ffc63cfb5..9525d5e1f24890 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/20] 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 1a4392523cf187..833d27d4957b38 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 476b19ba5c9cf9..d6f4fdf40ea306 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 9525d5e1f24890..99be29fb163bb6 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/20] 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 833d27d4957b38..2f7a8d944a5045 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/20] 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 2f7a8d944a5045..b7f9f65c71ad67 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 d6f4fdf40ea306..c92e80a351e1bd 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/20] 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 b7f9f65c71ad67..15e26f9baf68b9 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 c92e80a351e1bd..4146d9455bcd1d 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/20] 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 15e26f9baf68b9..1b0adc2ac6876a 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 4146d9455bcd1d..52b34fdbe2627c 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 99be29fb163bb6..4a43d8f3926d4f 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
More information about the cfe-commits
mailing list