llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-static-analyzer-1

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
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to