[libcxx-commits] [libcxx] [libc++] Replace __is_trivially_relocatable by is_trivially_copyable (PR #124970)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 29 13:10:21 PST 2025
================
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// Make sure we don't miscompile vector operations for types that shouldn't be considered
+// trivially relocatable.
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+
+struct Tracker {
+ std::size_t move_constructs = 0;
+};
+
+struct [[clang::trivial_abi]] Inner {
+ TEST_CONSTEXPR explicit Inner(Tracker* tracker) : tracker_(tracker) {}
+ TEST_CONSTEXPR Inner(const Inner& rhs) : tracker_(rhs.tracker_) { tracker_->move_constructs += 1; }
+ TEST_CONSTEXPR Inner(Inner&& rhs) : tracker_(rhs.tracker_) { tracker_->move_constructs += 1; }
+ Tracker* tracker_;
+};
+
+// Even though this type contains a trivial_abi type, it is not trivially move-constructible,
+// so we should not attempt to optimize its move construction + destroy using trivial relocation.
+struct NotTriviallyMovable {
+ TEST_CONSTEXPR explicit NotTriviallyMovable(Tracker* tracker) : inner_(tracker) {}
+ TEST_CONSTEXPR NotTriviallyMovable(NotTriviallyMovable&& other) : inner_(std::move(other.inner_)) {}
+ Inner inner_;
+};
+static_assert(!std::is_trivially_copyable<NotTriviallyMovable>::value, "");
+LIBCPP_STATIC_ASSERT(!std::__libcpp_is_trivially_relocatable<NotTriviallyMovable>::value, "");
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ Tracker track;
+ std::vector<NotTriviallyMovable> v;
+
+ // Fill the vector at its capacity, such that any subsequent push_back would require growing.
+ v.reserve(5);
+ for (std::size_t i = 0; i != 5; ++i) {
+ v.emplace_back(&track);
+ }
+ assert(track.move_constructs == 0);
+ assert(v.size() == 5);
----------------
philnik777 wrote:
This isn't portable, since implementations are allowed to allocate more memory than requested. You can just `emplace_back` until `v.size() == v.capacity()` instead to make it portable.
https://github.com/llvm/llvm-project/pull/124970
More information about the libcxx-commits
mailing list