[Mlir-commits] [clang] [clang-tools-extra] [flang] [libc] [llvm] [mlir] [clang-tidy] Fix invalid fixit from modernize-use-ranges for nullptr used with std::unique_ptr (PR #127162)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Feb 13 23:19:28 PST 2025
https://github.com/Andrewyuan34 updated https://github.com/llvm/llvm-project/pull/127162
>From 2026e73fe1b0ff2939d1ea4335028440b78f309e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20Clement=20=28=E3=83=90=E3=83=AC=E3=83=B3?=
=?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=B3=20=E3=82=AF=E3=83=AC=E3=83=A1?=
=?UTF-8?q?=E3=83=B3=29?= <clementval at gmail.com>
Date: Thu, 13 Feb 2025 18:59:24 -0800
Subject: [PATCH 01/10] [flang][cuda] Lower clock64 to nvvm intrinsic (#127155)
---
flang/include/flang/Optimizer/Builder/IntrinsicCall.h | 1 +
flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 11 +++++++++++
flang/module/cudadevice.f90 | 5 +++++
flang/test/Lower/CUDA/cuda-device-proc.cuf | 5 +++++
4 files changed, 22 insertions(+)
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index 47e8a77fa6aec..65732ce7f3224 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -231,6 +231,7 @@ struct IntrinsicLibrary {
void genCFProcPointer(llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genCFunLoc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genCLoc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+ mlir::Value genClock64(mlir::Type, llvm::ArrayRef<mlir::Value>);
template <mlir::arith::CmpIPredicate pred>
fir::ExtendedValue genCPtrCompare(mlir::Type,
llvm::ArrayRef<fir::ExtendedValue>);
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 3dc8d217ef38e..93744fa58ebc0 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -209,6 +209,7 @@ static constexpr IntrinsicHandler handlers[]{
&I::genChdir,
{{{"name", asAddr}, {"status", asAddr, handleDynamicOptional}}},
/*isElemental=*/false},
+ {"clock64", &I::genClock64, {}, /*isElemental=*/false},
{"cmplx",
&I::genCmplx,
{{{"x", asValue}, {"y", asValue, handleDynamicOptional}}}},
@@ -3228,6 +3229,16 @@ IntrinsicLibrary::genChdir(std::optional<mlir::Type> resultType,
return {};
}
+// CLOCK64
+mlir::Value IntrinsicLibrary::genClock64(mlir::Type resultType,
+ llvm::ArrayRef<mlir::Value> args) {
+ constexpr llvm::StringLiteral funcName = "llvm.nvvm.read.ptx.sreg.clock64";
+ mlir::MLIRContext *context = builder.getContext();
+ mlir::FunctionType ftype = mlir::FunctionType::get(context, {}, {resultType});
+ auto funcOp = builder.createFunction(loc, funcName, ftype);
+ return builder.create<fir::CallOp>(loc, funcOp, args).getResult(0);
+}
+
// CMPLX
mlir::Value IntrinsicLibrary::genCmplx(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
diff --git a/flang/module/cudadevice.f90 b/flang/module/cudadevice.f90
index 45b9f2c838638..ed126a1253908 100644
--- a/flang/module/cudadevice.f90
+++ b/flang/module/cudadevice.f90
@@ -628,5 +628,10 @@ attributes(device) pure integer function atomicdeci(address, val)
end interface
public :: atomicdec
+ interface
+ attributes(device) integer(8) function clock64()
+ end function
+ end interface
+ public :: clock64
end module
diff --git a/flang/test/Lower/CUDA/cuda-device-proc.cuf b/flang/test/Lower/CUDA/cuda-device-proc.cuf
index 17a6a1d965640..6a5524102c0ea 100644
--- a/flang/test/Lower/CUDA/cuda-device-proc.cuf
+++ b/flang/test/Lower/CUDA/cuda-device-proc.cuf
@@ -9,6 +9,7 @@ attributes(global) subroutine devsub()
real(8) :: ad
integer(4) :: ai
integer(8) :: al
+ integer(8) :: time
call syncthreads()
call syncwarp(1)
@@ -43,6 +44,8 @@ attributes(global) subroutine devsub()
ai = atomicor(ai, 1_4)
ai = atomicinc(ai, 1_4)
ai = atomicdec(ai, 1_4)
+
+ time = clock64()
end
! CHECK-LABEL: func.func @_QPdevsub() attributes {cuf.proc_attr = #cuf.cuda_proc<global>}
@@ -79,6 +82,8 @@ end
! CHECK: %{{.*}} = llvm.atomicrmw uinc_wrap %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i32
! CHECK: %{{.*}} = llvm.atomicrmw udec_wrap %{{.*}}, %{{.*}} seq_cst : !llvm.ptr, i32
+! CHECK: fir.call @llvm.nvvm.read.ptx.sreg.clock64()
+
subroutine host1()
integer, device :: a(32)
integer, device :: ret
>From 3e9c19bfa6f408137310171fd57c59f8da940ee1 Mon Sep 17 00:00:00 2001
From: Roland McGrath <mcgrathr at google.com>
Date: Thu, 13 Feb 2025 20:05:24 -0800
Subject: [PATCH 02/10] [libc] Make test macros suppress the -Wdangling-else
warnings (#127149)
Use the trick from gtest to allow `ASSERT_...` and `EXPECT_...`
macros to be used in braceless `if` without producing warnings
about the nested `if`-`else` that results.
---
libc/test/UnitTest/LibcTest.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h
index b4e3819ea958d..fbeafd0bacb75 100644
--- a/libc/test/UnitTest/LibcTest.h
+++ b/libc/test/UnitTest/LibcTest.h
@@ -400,6 +400,14 @@ CString libc_make_test_file_path_func(const char *file_name);
SuiteClass##_##TestName SuiteClass##_##TestName##_Instance; \
void SuiteClass##_##TestName::Run()
+// Helper to trick the compiler into ignoring lack of braces on the else
+// branch. We cannot introduce braces at this point, since it would prevent
+// using `<< ...` after the test macro for additional failure output.
+#define LIBC_TEST_DISABLE_DANGLING_ELSE \
+ switch (0) \
+ case 0: \
+ default: // NOLINT
+
// If RET_OR_EMPTY is the 'return' keyword we perform an early return which
// corresponds to an assert. If it is empty the execution continues, this
// corresponds to an expect.
@@ -411,6 +419,7 @@ CString libc_make_test_file_path_func(const char *file_name);
// returning a boolean. This expression is responsible for logging the
// diagnostic in case of failure.
#define LIBC_TEST_SCAFFOLDING_(TEST, RET_OR_EMPTY) \
+ LIBC_TEST_DISABLE_DANGLING_ELSE \
if (TEST) \
; \
else \
>From 0524eae33a5a7ac6764e7080ad561ba04c1ec906 Mon Sep 17 00:00:00 2001
From: NAKAMURA Takumi <geek4civic at gmail.com>
Date: Fri, 14 Feb 2025 11:33:44 +0900
Subject: [PATCH 03/10] SandboxIRTests: Use `EXPECT_DEBUG_DEATH` (for #126376)
---
llvm/unittests/SandboxIR/RegionTest.cpp | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/llvm/unittests/SandboxIR/RegionTest.cpp b/llvm/unittests/SandboxIR/RegionTest.cpp
index 201378980fe3b..09c578bcfefaa 100644
--- a/llvm/unittests/SandboxIR/RegionTest.cpp
+++ b/llvm/unittests/SandboxIR/RegionTest.cpp
@@ -362,9 +362,8 @@ define void @foo(i8 %v) {
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
-#ifndef NDEBUG
- EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI), ".*Gap*");
-#endif
+ EXPECT_DEBUG_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI),
+ ".*Gap*");
}
// Check that we get an assertion failure if we try to set the same index more
@@ -383,9 +382,8 @@ define void @foo(i8 %v) {
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
-#ifndef NDEBUG
- EXPECT_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI), ".*already.*");
-#endif // NDEBUG
+ EXPECT_DEBUG_DEATH(sandboxir::Region::createRegionsFromMD(*F, *TTI),
+ ".*already.*");
}
TEST_F(RegionTest, AuxRoundTrip) {
>From 907dca80268c1098bdff4306fe8dc6750fca9b9e Mon Sep 17 00:00:00 2001
From: Galen Elias <gelias at gmail.com>
Date: Thu, 13 Feb 2025 20:14:39 -0800
Subject: [PATCH 04/10] [clang-format] Support BraceWrapping.AfterNamespace
with AllowShortNamespacesOnASingleLine (#123010)
AllowShortNamespacesOnASingleLine assumes that there is no newline
before the namespace brace, however, there is no actual reason this
shouldn't be compatible with BraceWrapping.AfterNamespace = true.
This is a little tricky in the implementation because
UnwrappedLineFormatter works on lines, so being flexible about the
offsets is awkward.
Not sure if there is a better pattern for combining the 'AllowShort'
options with the various configurations of BraceWrapping, but this
seemed mostly reasonable. Really, it would almost be preferable to just
pattern match on the direct token stream, rather than the
AnnotatedLines, but I'm not seeing a straightforward way to do that.
---------
Co-authored-by: Owen Pan <owenpiano at gmail.com>
---
clang/lib/Format/UnwrappedLineFormatter.cpp | 48 +++++++++++++--------
clang/unittests/Format/FormatTest.cpp | 29 +++++++++++++
2 files changed, 60 insertions(+), 17 deletions(-)
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index a5b30c85974c7..dd667a9944515 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -366,8 +366,7 @@ class LineJoiner {
// instead of TheLine->First.
if (Style.AllowShortNamespacesOnASingleLine &&
- TheLine->First->is(tok::kw_namespace) &&
- TheLine->Last->is(tok::l_brace)) {
+ TheLine->First->is(tok::kw_namespace)) {
const auto result = tryMergeNamespace(I, E, Limit);
if (result > 0)
return result;
@@ -633,24 +632,37 @@ class LineJoiner {
if (Limit == 0)
return 0;
- assert(I[1]);
- const auto &L1 = *I[1];
+ // The merging code is relative to the opening namespace brace, which could
+ // be either on the first or second line due to the brace wrapping rules.
+ const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace;
+ const auto *BraceOpenLine = I + OpenBraceWrapped;
+
+ assert(*BraceOpenLine);
+ if (BraceOpenLine[0]->Last->isNot(TT_NamespaceLBrace))
+ return 0;
+
+ if (std::distance(BraceOpenLine, E) <= 2)
+ return 0;
+
+ if (BraceOpenLine[0]->Last->is(tok::comment))
+ return 0;
+
+ assert(BraceOpenLine[1]);
+ const auto &L1 = *BraceOpenLine[1];
if (L1.InPPDirective != (*I)->InPPDirective ||
(L1.InPPDirective && L1.First->HasUnescapedNewline)) {
return 0;
}
- if (std::distance(I, E) <= 2)
- return 0;
-
- assert(I[2]);
- const auto &L2 = *I[2];
+ assert(BraceOpenLine[2]);
+ const auto &L2 = *BraceOpenLine[2];
if (L2.Type == LT_Invalid)
return 0;
Limit = limitConsideringMacros(I + 1, E, Limit);
- if (!nextTwoLinesFitInto(I, Limit))
+ const auto LinesToBeMerged = OpenBraceWrapped + 2;
+ if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit))
return 0;
// Check if it's a namespace inside a namespace, and call recursively if so.
@@ -661,17 +673,19 @@ class LineJoiner {
assert(Limit >= L1.Last->TotalLength + 3);
const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
- const auto MergedLines = tryMergeNamespace(I + 1, E, InnerLimit);
+ const auto MergedLines =
+ tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit);
if (MergedLines == 0)
return 0;
- const auto N = MergedLines + 2;
+ const auto N = MergedLines + LinesToBeMerged;
// Check if there is even a line after the inner result.
if (std::distance(I, E) <= N)
return 0;
// Check that the line after the inner result starts with a closing brace
// which we are permitted to merge into one line.
- if (I[N]->First->is(tok::r_brace) && !I[N]->First->MustBreakBefore &&
- I[MergedLines + 1]->Last->isNot(tok::comment) &&
+ if (I[N]->First->is(TT_NamespaceRBrace) &&
+ !I[N]->First->MustBreakBefore &&
+ BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) &&
nextNLinesFitInto(I, I + N + 1, Limit)) {
return N;
}
@@ -686,11 +700,11 @@ class LineJoiner {
return 0;
// Last, check that the third line starts with a closing brace.
- if (L2.First->isNot(tok::r_brace) || L2.First->MustBreakBefore)
+ if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore)
return 0;
- // If so, merge all three lines.
- return 2;
+ // If so, merge all lines.
+ return LinesToBeMerged;
}
unsigned
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 9b9ce35f83bc5..2365a7c40bf76 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -28867,6 +28867,35 @@ TEST_F(FormatTest, ShortNamespacesOption) {
"}}} // namespace foo::bar::baz",
"namespace foo { namespace bar { namespace baz { class qux; } } }",
Style);
+ Style.FixNamespaceComments = false;
+
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterNamespace = true;
+ verifyFormat("namespace foo { class bar; }", Style);
+ verifyFormat("namespace foo { namespace bar { class baz; } }", Style);
+ verifyFormat("namespace foo\n"
+ "{ // comment\n"
+ "class bar;\n"
+ "}",
+ Style);
+ verifyFormat("namespace foo { class bar; }",
+ "namespace foo {\n"
+ "class bar;\n"
+ "}",
+ Style);
+ verifyFormat("namespace foo\n"
+ "{\n"
+ "namespace bar\n"
+ "{ // comment\n"
+ "class baz;\n"
+ "}\n"
+ "}",
+ Style);
+ verifyFormat("namespace foo // comment\n"
+ "{\n"
+ "class baz;\n"
+ "}",
+ Style);
}
TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) {
>From 6130e069fe10524cea11082c3d22cbf4ea97fce4 Mon Sep 17 00:00:00 2001
From: schittir <sindhu.chittireddy at intel.com>
Date: Thu, 13 Feb 2025 21:14:36 -0800
Subject: [PATCH 05/10] [clang][NFC] Avoid potential null dereferences
(#127017)
Add null checking.
---
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 4 ++--
clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index b679d63874b3b..9f7db25a15bec 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -7447,7 +7447,7 @@ class MappableExprsHandler {
// Update info about the lowest and highest elements for this struct
if (!PartialStruct.Base.isValid()) {
PartialStruct.LowestElem = {FieldIndex, LowestElem};
- if (IsFinalArraySection) {
+ if (IsFinalArraySection && OASE) {
Address HB =
CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
.getAddress();
@@ -7460,7 +7460,7 @@ class MappableExprsHandler {
} else if (FieldIndex < PartialStruct.LowestElem.first) {
PartialStruct.LowestElem = {FieldIndex, LowestElem};
} else if (FieldIndex > PartialStruct.HighestElem.first) {
- if (IsFinalArraySection) {
+ if (IsFinalArraySection && OASE) {
Address HB =
CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false)
.getAddress();
diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index 12bf12a0b2322..8955cb209c399 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -314,6 +314,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE,
RegionArgIsBad = true;
}
+ assert(ArgSM);
// Is the argument to the call being tracked?
const AllocationState *AS = State->get<AllocatedData>(ArgSM);
if (!AS)
>From 717f13372c236b956da5b1647884f239e7527f6b Mon Sep 17 00:00:00 2001
From: Srinivasa Ravi <srinivasar at nvidia.com>
Date: Fri, 14 Feb 2025 11:11:44 +0530
Subject: [PATCH 06/10] [NVPTX] Add intrinsics for redux.sync f32 instructions
(#126664)
Adds NVVM intrinsics, NVPTX codegen and Clang builtins for `redux.sync`
f32 instructions introduced in ptx8.6 for sm_100a.
Tests added in `CodeGen/NVPTX/redux-sync.ll` and
`CodeGenCUDA/redux-builtins.cu` and verified through ptxas 12.8.0.
PTX Spec Reference:
https://docs.nvidia.com/cuda/parallel-thread-execution/#parallel-synchronization-and-communication-instructions-redux-sync
---
clang/include/clang/Basic/BuiltinsNVPTX.td | 8 ++
clang/test/CodeGenCUDA/redux-f32-builtins.cu | 34 +++++
llvm/include/llvm/IR/IntrinsicsNVVM.td | 12 ++
llvm/lib/Target/NVPTX/NVPTXIntrinsics.td | 19 +++
llvm/test/CodeGen/NVPTX/redux-sync-f32.ll | 139 +++++++++++++++++++
5 files changed, 212 insertions(+)
create mode 100644 clang/test/CodeGenCUDA/redux-f32-builtins.cu
create mode 100644 llvm/test/CodeGen/NVPTX/redux-sync-f32.ll
diff --git a/clang/include/clang/Basic/BuiltinsNVPTX.td b/clang/include/clang/Basic/BuiltinsNVPTX.td
index 9d24a992563a4..327dc88cffdb4 100644
--- a/clang/include/clang/Basic/BuiltinsNVPTX.td
+++ b/clang/include/clang/Basic/BuiltinsNVPTX.td
@@ -669,6 +669,14 @@ def __nvvm_redux_sync_umax : NVPTXBuiltinSMAndPTX<"unsigned int(unsigned int, in
def __nvvm_redux_sync_and : NVPTXBuiltinSMAndPTX<"int(int, int)", SM_80, PTX70>;
def __nvvm_redux_sync_xor : NVPTXBuiltinSMAndPTX<"int(int, int)", SM_80, PTX70>;
def __nvvm_redux_sync_or : NVPTXBuiltinSMAndPTX<"int(int, int)", SM_80, PTX70>;
+def __nvvm_redux_sync_fmin : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmin_abs : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmin_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmin_abs_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmax : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmax_abs : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmax_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
+def __nvvm_redux_sync_fmax_abs_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>;
// Membar
diff --git a/clang/test/CodeGenCUDA/redux-f32-builtins.cu b/clang/test/CodeGenCUDA/redux-f32-builtins.cu
new file mode 100644
index 0000000000000..7359fb0006991
--- /dev/null
+++ b/clang/test/CodeGenCUDA/redux-f32-builtins.cu
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 "-triple" "nvptx-nvidia-cuda" "-target-feature" "+ptx86" "-target-cpu" "sm_100a" -emit-llvm -fcuda-is-device -o - %s | FileCheck %s
+// RUN: %clang_cc1 "-triple" "nvptx64-nvidia-cuda" "-target-feature" "+ptx86" "-target-cpu" "sm_100a" -emit-llvm -fcuda-is-device -o - %s | FileCheck %s
+
+// CHECK: define{{.*}} void @_Z6kernelPf(ptr noundef %out_f)
+__attribute__((global)) void kernel(float* out_f) {
+ float a = 3.0;
+ int i = 0;
+
+ out_f[i++] = __nvvm_redux_sync_fmin(a, 0xFF);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmin
+
+ out_f[i++] = __nvvm_redux_sync_fmin_abs(a, 0xFF);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmin.abs
+
+ out_f[i++] = __nvvm_redux_sync_fmin_NaN(a, 0xF0);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmin.NaN
+
+ out_f[i++] = __nvvm_redux_sync_fmin_abs_NaN(a, 0x0F);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmin.abs.NaN
+
+ out_f[i++] = __nvvm_redux_sync_fmax(a, 0xFF);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmax
+
+ out_f[i++] = __nvvm_redux_sync_fmax_abs(a, 0x01);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmax.abs
+
+ out_f[i++] = __nvvm_redux_sync_fmax_NaN(a, 0xF1);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmax.NaN
+
+ out_f[i++] = __nvvm_redux_sync_fmax_abs_NaN(a, 0x10);
+ // CHECK: call contract float @llvm.nvvm.redux.sync.fmax.abs.NaN
+
+ // CHECK: ret void
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsNVVM.td b/llvm/include/llvm/IR/IntrinsicsNVVM.td
index 1a6aa17b531c6..7ef270f3256a6 100644
--- a/llvm/include/llvm/IR/IntrinsicsNVVM.td
+++ b/llvm/include/llvm/IR/IntrinsicsNVVM.td
@@ -4824,6 +4824,18 @@ def int_nvvm_redux_sync_xor : ClangBuiltin<"__nvvm_redux_sync_xor">,
def int_nvvm_redux_sync_or : ClangBuiltin<"__nvvm_redux_sync_or">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
[IntrConvergent, IntrInaccessibleMemOnly, IntrNoCallback]>;
+
+// redux.sync.op.{abs}.{NaN}.f32 dst, src, membermask;
+foreach binOp = ["min", "max"] in {
+ foreach abs = ["", "_abs"] in {
+ foreach NaN = ["", "_NaN"] in {
+ def int_nvvm_redux_sync_f # binOp # abs # NaN :
+ ClangBuiltin<!strconcat("__nvvm_redux_sync_f", binOp, abs, NaN)>,
+ Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_i32_ty],
+ [IntrConvergent, IntrInaccessibleMemOnly, IntrNoCallback]>;
+ }
+ }
+}
//
// WGMMA fence instructions
diff --git a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td
index 6a99a4b3b4f69..f20502521829e 100644
--- a/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td
+++ b/llvm/lib/Target/NVPTX/NVPTXIntrinsics.td
@@ -328,6 +328,25 @@ defm REDUX_SYNC_AND : REDUX_SYNC<"and", "b32", int_nvvm_redux_sync_and>;
defm REDUX_SYNC_XOR : REDUX_SYNC<"xor", "b32", int_nvvm_redux_sync_xor>;
defm REDUX_SYNC_OR : REDUX_SYNC<"or", "b32", int_nvvm_redux_sync_or>;
+multiclass REDUX_SYNC_F<string BinOp, string abs, string NaN> {
+ defvar intr_name = "int_nvvm_redux_sync_f" # BinOp # !subst(".", "_", abs) # !subst(".", "_", NaN);
+
+ def : NVPTXInst<(outs Float32Regs:$dst),
+ (ins Float32Regs:$src, Int32Regs:$mask),
+ "redux.sync." # BinOp # abs # NaN # ".f32 $dst, $src, $mask;",
+ [(set f32:$dst, (!cast<Intrinsic>(intr_name) f32:$src, Int32Regs:$mask))]>,
+ Requires<[hasPTX<86>, hasSM100a]>;
+}
+
+defm REDUX_SYNC_FMIN : REDUX_SYNC_F<"min", "", "">;
+defm REDUX_SYNC_FMIN_ABS : REDUX_SYNC_F<"min", ".abs", "">;
+defm REDUX_SYNC_FMIN_NAN: REDUX_SYNC_F<"min", "", ".NaN">;
+defm REDUX_SYNC_FMIN_ABS_NAN: REDUX_SYNC_F<"min", ".abs", ".NaN">;
+defm REDUX_SYNC_FMAX : REDUX_SYNC_F<"max", "", "">;
+defm REDUX_SYNC_FMAX_ABS : REDUX_SYNC_F<"max", ".abs", "">;
+defm REDUX_SYNC_FMAX_NAN: REDUX_SYNC_F<"max", "", ".NaN">;
+defm REDUX_SYNC_FMAX_ABS_NAN: REDUX_SYNC_F<"max", ".abs", ".NaN">;
+
} // isConvergent = true
//-----------------------------------
diff --git a/llvm/test/CodeGen/NVPTX/redux-sync-f32.ll b/llvm/test/CodeGen/NVPTX/redux-sync-f32.ll
new file mode 100644
index 0000000000000..af113e75fd143
--- /dev/null
+++ b/llvm/test/CodeGen/NVPTX/redux-sync-f32.ll
@@ -0,0 +1,139 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_100a -mattr=+ptx86 | FileCheck %s
+; RUN: %if ptxas-12.8 %{ llc < %s -mtriple=nvptx64 -mcpu=sm_100a -mattr=+ptx86 | %ptxas-verify -arch=sm_100a %}
+
+declare float @llvm.nvvm.redux.sync.fmin(float, i32)
+define float @redux_sync_fmin(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmin(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmin_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmin_param_1];
+; CHECK-NEXT: redux.sync.min.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmin(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmin.abs(float, i32)
+define float @redux_sync_fmin_abs(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmin_abs(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmin_abs_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmin_abs_param_1];
+; CHECK-NEXT: redux.sync.min.abs.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmin.abs(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmin.NaN(float, i32)
+define float @redux_sync_fmin_NaN(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmin_NaN(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmin_NaN_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmin_NaN_param_1];
+; CHECK-NEXT: redux.sync.min.NaN.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmin.NaN(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmin.abs.NaN(float, i32)
+define float @redux_sync_fmin_abs_NaN(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmin_abs_NaN(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmin_abs_NaN_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmin_abs_NaN_param_1];
+; CHECK-NEXT: redux.sync.min.abs.NaN.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmin.abs.NaN(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmax(float, i32)
+define float @redux_sync_fmax(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmax(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmax_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmax_param_1];
+; CHECK-NEXT: redux.sync.max.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmax(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmax.abs(float, i32)
+define float @redux_sync_fmax_abs(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmax_abs(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmax_abs_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmax_abs_param_1];
+; CHECK-NEXT: redux.sync.max.abs.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmax.abs(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmax.NaN(float, i32)
+define float @redux_sync_fmax_NaN(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmax_NaN(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmax_NaN_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmax_NaN_param_1];
+; CHECK-NEXT: redux.sync.max.NaN.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmax.NaN(float %src, i32 %mask)
+ ret float %val
+}
+
+declare float @llvm.nvvm.redux.sync.fmax.abs.NaN(float, i32)
+define float @redux_sync_fmax_abs_NaN(float %src, i32 %mask) {
+; CHECK-LABEL: redux_sync_fmax_abs_NaN(
+; CHECK: {
+; CHECK-NEXT: .reg .b32 %r<2>;
+; CHECK-NEXT: .reg .f32 %f<3>;
+; CHECK-EMPTY:
+; CHECK-NEXT: // %bb.0:
+; CHECK-NEXT: ld.param.f32 %f1, [redux_sync_fmax_abs_NaN_param_0];
+; CHECK-NEXT: ld.param.u32 %r1, [redux_sync_fmax_abs_NaN_param_1];
+; CHECK-NEXT: redux.sync.max.abs.NaN.f32 %f2, %f1, %r1;
+; CHECK-NEXT: st.param.f32 [func_retval0], %f2;
+; CHECK-NEXT: ret;
+ %val = call float @llvm.nvvm.redux.sync.fmax.abs.NaN(float %src, i32 %mask)
+ ret float %val
+}
>From 1270377a93c0c8b80cd21fccf577616451c436de Mon Sep 17 00:00:00 2001
From: Uday Bondhugula <uday at polymagelabs.com>
Date: Fri, 14 Feb 2025 11:25:07 +0530
Subject: [PATCH 07/10] [MLIR][Affine] Add affine value map difference operator
(#127163)
Add affine value map difference operator. NFC otherwise.
---
mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h | 7 +++++++
mlir/lib/Dialect/Affine/Analysis/Utils.cpp | 4 +---
mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp | 8 ++++++++
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h b/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h
index 7ad0e4a1e5ea0..ac480d6997ef4 100644
--- a/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h
+++ b/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h
@@ -84,6 +84,13 @@ class AffineValueMap {
/// and/or operands have been modified.
LogicalResult canonicalize();
+ /// Checks if the application of this map to its operands is semantically
+ /// equal to `other`'s.
+ bool operator==(const AffineValueMap &other) const;
+ bool operator!=(const AffineValueMap &other) const {
+ return !(*this == other);
+ }
+
private:
// A mutable affine map.
MutableAffineMap map;
diff --git a/mlir/lib/Dialect/Affine/Analysis/Utils.cpp b/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
index b829633252fdd..93d8bffdcd8a4 100644
--- a/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
+++ b/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
@@ -2001,9 +2001,7 @@ bool MemRefAccess::operator==(const MemRefAccess &rhs) const {
AffineValueMap diff, thisMap, rhsMap;
getAccessMap(&thisMap);
rhs.getAccessMap(&rhsMap);
- AffineValueMap::difference(thisMap, rhsMap, &diff);
- return llvm::all_of(diff.getAffineMap().getResults(),
- [](AffineExpr e) { return e == 0; });
+ return thisMap == rhsMap;
}
void mlir::affine::getAffineIVs(Operation &op, SmallVectorImpl<Value> &ivs) {
diff --git a/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp b/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
index 6a52849186872..6d2d3212c696b 100644
--- a/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
+++ b/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
@@ -109,4 +109,12 @@ ArrayRef<Value> AffineValueMap::getOperands() const {
AffineMap AffineValueMap::getAffineMap() const { return map.getAffineMap(); }
+bool AffineValueMap::operator==(const AffineValueMap &other) const {
+ AffineValueMap diff;
+ AffineValueMap::difference(*this, other, &diff);
+ return llvm::all_of(diff.getAffineMap().getResults(), [](AffineExpr e) {
+ return e == getAffineConstantExpr(0, e.getContext());
+ });
+}
+
AffineValueMap::~AffineValueMap() = default;
>From e2a0f5074ef332007557e3c4b3a0f44a4bf3b5c6 Mon Sep 17 00:00:00 2001
From: serge-sans-paille <sguelton at mozilla.com>
Date: Fri, 14 Feb 2025 06:20:30 +0000
Subject: [PATCH 08/10] [clang][cmake] Sanitize CLANG_BOLT values (#126768)
This avoids failing later in the build process.
---
clang/tools/driver/CMakeLists.txt | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt
index ad336fcc45b60..5d7962769014a 100644
--- a/clang/tools/driver/CMakeLists.txt
+++ b/clang/tools/driver/CMakeLists.txt
@@ -23,10 +23,14 @@ if(CLANG_PLUGIN_SUPPORT)
set(support_plugins SUPPORT_PLUGINS)
endif()
+set(CLANG_BOLT_ALLOWLIST INSTRUMENT PERF LBR)
set(CLANG_BOLT OFF CACHE STRING "Apply BOLT optimization to Clang. \
- May be specified as Instrument or Perf or LBR to use a particular profiling \
+May be specified as one of ${CLANG_BOLT_ALLOWLIST} to use a particular profiling \
mechanism.")
string(TOUPPER "${CLANG_BOLT}" CLANG_BOLT)
+if (CLANG_BOLT AND NOT CLANG_BOLT IN_LIST CLANG_BOLT_ALLOWLIST)
+ message(FATAL_ERROR "Specified CLANG_BOLT value '${CLANG_BOLT}' is not one of ${CLANG_BOLT_ALLOWLIST}.")
+endif()
if (CLANG_BOLT AND NOT LLVM_BUILD_INSTRUMENTED)
set(CLANG_BOLT_DEPS clear-bolt-fdata llvm-bolt llvm-readobj)
>From a704026002e70cc84f6eb138723f5323ff501f6f Mon Sep 17 00:00:00 2001
From: Andrewyuan34 <yiboy at uvic.ca>
Date: Thu, 13 Feb 2025 22:35:36 -0500
Subject: [PATCH 09/10] [clang-tidy] Fix invalid fixit from
modernize-use-ranges for nullptr used with std::unique_ptr
---
.../clang-tidy/utils/UseRangesCheck.cpp | 10 ++++++++
.../checkers/modernize/use-ranges.cpp | 25 ++++++++++++++++---
2 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp
index aba4d17ccd035..4c5db488dce7f 100644
--- a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp
@@ -215,6 +215,16 @@ void UseRangesCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Call = Result.Nodes.getNodeAs<CallExpr>(Buffer);
if (!Call)
continue;
+ if (Function->getName() == "find") {
+ unsigned ValueArgIndex = 2;
+ if (Call->getNumArgs() <= ValueArgIndex)
+ continue;
+ const Expr *ValueExpr =
+ Call->getArg(ValueArgIndex)->IgnoreParenImpCasts();
+ if (isa<CXXNullPtrLiteralExpr>(ValueExpr)) {
+ return;
+ }
+ }
auto Diag = createDiag(*Call);
if (auto ReplaceName = Replacer->getReplaceName(*Function))
Diag << FixItHint::CreateReplacement(Call->getCallee()->getSourceRange(),
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp
index b022efebfdf4d..57ca038f64511 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp
@@ -1,14 +1,24 @@
-// RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t -- -- -I %S/Inputs/use-ranges/
-// RUN: %check_clang_tidy -std=c++23 %s modernize-use-ranges %t -check-suffixes=,CPP23 -- -I %S/Inputs/use-ranges/
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t -- -- -I %S/Inputs/
+// RUN: %check_clang_tidy -std=c++23 %s modernize-use-ranges %t -check-suffixes=,CPP23 -- -I %S/Inputs/
+// Example: ./check_clang_tidy.py -std=c++20 checkers/modernize/use-ranges.cpp modernize-use-ranges temp.txt -- -- -I ~/llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/
// CHECK-FIXES: #include <algorithm>
// CHECK-FIXES-CPP23: #include <numeric>
// CHECK-FIXES: #include <ranges>
-#include "fake_std.h"
+#include "use-ranges/fake_std.h"
+#include "smart-ptr/unique_ptr.h"
void Positives() {
std::vector<int> I, J;
+
+ // Expect to have no check messages
+ std::find(I.begin(), I.end(), nullptr);
+
+ std::find(I.begin(), I.end(), std::unique_ptr<int>());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
+ // CHECK-FIXES: std::ranges::find(I, std::unique_ptr<int>());
+
std::find(I.begin(), I.end(), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
// CHECK-FIXES: std::ranges::find(I, 0);
@@ -76,6 +86,14 @@ void Positives() {
void Reverse(){
std::vector<int> I, J;
+
+ // Expect to have no check messages
+ std::find(I.rbegin(), I.rend(), nullptr);
+
+ std::find(I.rbegin(), I.rend(), std::unique_ptr<int>());
+ // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
+ // CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(I), std::unique_ptr<int>());
+
std::find(I.rbegin(), I.rend(), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
// CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(I), 0);
@@ -112,3 +130,4 @@ void Negatives() {
// Pathological, but probably shouldn't diagnose this
std::rotate(I.begin(), I.end(), I.end() + 0);
}
+
>From 6943df4e0cda78858305f37b590613885cf2d291 Mon Sep 17 00:00:00 2001
From: Andrewyuan34 <yiboy at uvic.ca>
Date: Fri, 14 Feb 2025 01:15:46 -0500
Subject: [PATCH 10/10] Based on PR reviews, improve code quality by making
sure const correctness and modifying code format
Co-authored-by: Piotr Zegar <me at piotrzegar.pl>
---
.../clang-tidy/utils/UseRangesCheck.cpp | 5 ++---
clang-tools-extra/docs/ReleaseNotes.rst | 3 +++
.../clang-tidy/checkers/modernize/use-ranges.cpp | 15 ++++++++-------
3 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp
index 4c5db488dce7f..ce86a27ad69b2 100644
--- a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp
+++ b/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp
@@ -216,14 +216,13 @@ void UseRangesCheck::check(const MatchFinder::MatchResult &Result) {
if (!Call)
continue;
if (Function->getName() == "find") {
- unsigned ValueArgIndex = 2;
+ const unsigned ValueArgIndex = 2;
if (Call->getNumArgs() <= ValueArgIndex)
continue;
const Expr *ValueExpr =
Call->getArg(ValueArgIndex)->IgnoreParenImpCasts();
- if (isa<CXXNullPtrLiteralExpr>(ValueExpr)) {
+ if (isa<CXXNullPtrLiteralExpr>(ValueExpr))
return;
- }
}
auto Diag = createDiag(*Call);
if (auto ReplaceName = Replacer->getReplaceName(*Function))
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 6b8fe22242417..5ad4fb7270ac1 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -109,6 +109,9 @@ Changes in existing checks
- Improved :doc:`misc-redundant-expression
<clang-tidy/checks/misc/redundant-expression>` check by providing additional
examples and fixing some macro related false positives.
+
+- Fixed a false positive in :doc:`modernize-use-ranges
+ <clang-tidy/checks/modernize/use-ranges>`updat the logic to suppress warnings for `nullptr` in `std::find`.
Removed checks
^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp
index 57ca038f64511..5aa026038b1cd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp
@@ -11,13 +11,14 @@
void Positives() {
std::vector<int> I, J;
+ std::vector<std::unique_ptr<int>> K;
// Expect to have no check messages
- std::find(I.begin(), I.end(), nullptr);
+ std::find(K.begin(), K.end(), nullptr);
- std::find(I.begin(), I.end(), std::unique_ptr<int>());
+ std::find(K.begin(), K.end(), std::unique_ptr<int>());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
- // CHECK-FIXES: std::ranges::find(I, std::unique_ptr<int>());
+ // CHECK-FIXES: std::ranges::find(K, std::unique_ptr<int>());
std::find(I.begin(), I.end(), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
@@ -86,13 +87,14 @@ void Positives() {
void Reverse(){
std::vector<int> I, J;
+ std::vector<std::unique_ptr<int>> K;
// Expect to have no check messages
- std::find(I.rbegin(), I.rend(), nullptr);
+ std::find(K.rbegin(), K.rend(), nullptr);
- std::find(I.rbegin(), I.rend(), std::unique_ptr<int>());
+ std::find(K.rbegin(), K.rend(), std::unique_ptr<int>());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
- // CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(I), std::unique_ptr<int>());
+ // CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(K), std::unique_ptr<int>());
std::find(I.rbegin(), I.rend(), 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
@@ -130,4 +132,3 @@ void Negatives() {
// Pathological, but probably shouldn't diagnose this
std::rotate(I.begin(), I.end(), I.end() + 0);
}
-
More information about the Mlir-commits
mailing list