https://github.com/gamesh411 created 
https://github.com/llvm/llvm-project/pull/177804

…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`.

From e3ce3086bf5c545406219bcfc1ceb90befd1d335 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <[email protected]>
Date: Sat, 24 Jan 2026 22:38:58 +0100
Subject: [PATCH] [clang][analyzer] Suppress false positives in
 std::stable_sort and std::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`.
---
 .../Core/BugReporterVisitors.cpp              | 16 +++++++++
 ...tem-header-simulator-cxx-std-suppression.h | 35 +++++++++++++++++++
 .../implicit-cxx-std-suppression.cpp          | 10 ++++++
 3 files changed, 61 insertions(+)

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
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to