[clang] [clang][analyzer] Suppress false positives in std::stable_sort and st… (PR #177804)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 24 14:28:04 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Endre Fülöp (gamesh411)
<details>
<summary>Changes</summary>
…d::inplace_merge
The analyzer reports false positives in `std::stable_sort` and `std::inplace_merge` due to complex move semantics in `__uninitialized_construct_buf_dispatch::__ucr`.
Add suppression for this STL internal function, following the pattern of existing suppressions for `std::basic_string` and `std::shared_ptr`.
---
Full diff: https://github.com/llvm/llvm-project/pull/177804.diff
3 Files Affected:
- (modified) clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (+16)
- (modified) clang/test/Analysis/Inputs/system-header-simulator-cxx-std-suppression.h (+35)
- (modified) clang/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp (+10)
``````````diff
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 7df5fab0843ac..65e2ed5a28313 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -3305,6 +3305,22 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
}
}
+ // Suppress false positives in std::stable_sort and std::inplace_merge.
+ // The analyzer reports uninitialized values in the
+ // __uninitialized_construct_buf_dispatch::__ucr method used by those
+ // algorithms due to complex move semantics with placement new.
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->getName() == "__ucr") {
+ if (const auto *RD = dyn_cast<CXXRecordDecl>(FD->getParent())) {
+ if (RD->getName().starts_with(
+ "__uninitialized_construct_buf_dispatch")) {
+ BR.markInvalid(getTag(), nullptr);
+ return;
+ }
+ }
+ }
+ }
+
for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
LCtx = LCtx->getParent()) {
const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx-std-suppression.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx-std-suppression.h
index dc53af269c9c2..b7d61b2955f3c 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-cxx-std-suppression.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx-std-suppression.h
@@ -142,5 +142,40 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t) {
}
#endif // __has_feature(cxx_decltype)
+
+// Mock for __uninitialized_construct_buf_dispatch::__ucr suppression.
+// std::stable_sort uses _Temporary_buffer which calls
+// __uninitialized_construct_buf_dispatch::__ucr internally.
+// The analyzer seems to lose track of initialization state in __ucr's complex
+// move semantics, leading to false positives.
+namespace __uninitialized_construct_buf_dispatch_impl {
+template <bool>
+struct __uninitialized_construct_buf_dispatch {
+ template <typename _Pointer, typename _ForwardIterator>
+ static _Pointer __ucr(_Pointer __first, _ForwardIterator __last) {
+ // Fake error trigger.
+ int z = 0;
+ z = 5/z;
+ return __first;
+ }
+};
+} // namespace __uninitialized_construct_buf_dispatch_impl
+
+template <typename _RandomAccessIterator>
+void stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) {
+ // Calls __ucr internally, matching real STL implementation.
+ __uninitialized_construct_buf_dispatch_impl::
+ __uninitialized_construct_buf_dispatch<false>::__ucr(__first, __last);
}
+template <typename _BidirectionalIterator>
+void inplace_merge(_BidirectionalIterator __first,
+ _BidirectionalIterator __middle,
+ _BidirectionalIterator __last) {
+ // Also uses _Temporary_buffer which calls __ucr internally.
+ __uninitialized_construct_buf_dispatch_impl::
+ __uninitialized_construct_buf_dispatch<false>::__ucr(__first, __middle);
+}
+
+} // namespace std
+
diff --git a/clang/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp b/clang/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp
index 35f8798c81ae1..f49d6f78c165a 100644
--- a/clang/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp
+++ b/clang/test/Analysis/diagnostics/implicit-cxx-std-suppression.cpp
@@ -37,3 +37,13 @@ void testSuppression_std_shared_pointer() {
p = nullptr; // no-warning
}
+
+void testSuppression_stable_sort() {
+ int arr[5];
+ std::stable_sort(arr, arr + 5); // no-warning
+}
+
+void testSuppression_inplace_merge() {
+ int arr[5];
+ std::inplace_merge(arr, arr + 2, arr + 5); // no-warning
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/177804
More information about the cfe-commits
mailing list