diff options
-rw-r--r-- | pw_bluetooth/public/pw_bluetooth/gatt/client.h | 3 | ||||
-rw-r--r-- | pw_containers/BUILD.bazel | 1 | ||||
-rw-r--r-- | pw_containers/BUILD.gn | 2 | ||||
-rw-r--r-- | pw_containers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | pw_containers/public/pw_containers/vector.h | 14 | ||||
-rw-r--r-- | pw_containers/vector_test.cc | 40 |
6 files changed, 42 insertions, 19 deletions
diff --git a/pw_bluetooth/public/pw_bluetooth/gatt/client.h b/pw_bluetooth/public/pw_bluetooth/gatt/client.h index e12de22be..47e4b2038 100644 --- a/pw_bluetooth/public/pw_bluetooth/gatt/client.h +++ b/pw_bluetooth/public/pw_bluetooth/gatt/client.h @@ -46,7 +46,8 @@ class RemoteService { Handle handle; /// The value of the characteristic or descriptor. - Vector<std::byte> value; + // TODO: b/320482584 - Consider changing capacity or making it configurable + Vector<std::byte, 20> value; /// True if `value` might be truncated (the buffer was completely filled by /// the server and the read was a short read). `ReadCharacteristic` or diff --git a/pw_containers/BUILD.bazel b/pw_containers/BUILD.bazel index 417ba3f32..4b57a7c54 100644 --- a/pw_containers/BUILD.bazel +++ b/pw_containers/BUILD.bazel @@ -213,6 +213,7 @@ pw_cc_test( deps = [ ":pw_containers", ":test_helpers", + "//pw_compilation_testing:negative_compilation_testing", "//pw_unit_test", ], ) diff --git a/pw_containers/BUILD.gn b/pw_containers/BUILD.gn index 1bc4fd29b..f5ab5824e 100644 --- a/pw_containers/BUILD.gn +++ b/pw_containers/BUILD.gn @@ -255,6 +255,8 @@ pw_test("vector_test") { ":vector", ] + negative_compilation_tests = true + # TODO: b/259746255 - Remove this when everything compiles with -Wconversion. configs = [ "$dir_pw_build:conversion_warnings" ] } diff --git a/pw_containers/CMakeLists.txt b/pw_containers/CMakeLists.txt index d0bdcfda0..a27f2f3d5 100644 --- a/pw_containers/CMakeLists.txt +++ b/pw_containers/CMakeLists.txt @@ -243,6 +243,7 @@ pw_add_test(pw_containers.vector_test SOURCES vector_test.cc PRIVATE_DEPS + pw_compilation_testing._pigweed_only_negative_compilation pw_containers._test_helpers pw_containers.vector GROUPS diff --git a/pw_containers/public/pw_containers/vector.h b/pw_containers/public/pw_containers/vector.h index 81bbeb705..750312e38 100644 --- a/pw_containers/public/pw_containers/vector.h +++ b/pw_containers/public/pw_containers/vector.h @@ -76,7 +76,7 @@ class Vector using typename Vector<T, vector_impl::kGeneric>::const_reverse_iterator; // Construct - Vector() noexcept {} + Vector() noexcept = default; Vector(size_type count, const T& value) { this->Append(count, value); } @@ -147,9 +147,6 @@ class Vector return *this; } - // Allow `delete` with non-polymorphic-sized vectors. - static void operator delete(void* ptr) { ::operator delete(ptr); } - // All other vector methods are implemented on the Vector<T> base class. }; @@ -271,6 +268,7 @@ class Vector<T, vector_impl::kGeneric> { // A vector without an explicit maximum size (Vector<T>) cannot be constructed // directly. Instead, construct a Vector<T, kMaxSize>. Vectors of any max size // can be used through a Vector<T> pointer or reference. + Vector() = delete; // Assign @@ -433,6 +431,10 @@ class Vector<T, vector_impl::kGeneric> { explicit constexpr Vector(size_type max_size) noexcept : max_size_(max_size) {} + // Polymorphic-sized vectors cannot be destroyed directly due to the lack of a + // virtual destructor. + ~Vector() = default; + template <typename Iterator> void CopyFrom(Iterator first, Iterator last); @@ -444,10 +446,6 @@ class Vector<T, vector_impl::kGeneric> { iterator InsertFrom(const_iterator index, Iterator first, Iterator last); private: - // Polymorphic-sized vectors cannot be `delete`d due to the lack of a virtual - // destructor. - static void operator delete(void*); - const size_type max_size_; size_type size_ = 0; }; diff --git a/pw_containers/vector_test.cc b/pw_containers/vector_test.cc index 0a69dae39..bc0d5388b 100644 --- a/pw_containers/vector_test.cc +++ b/pw_containers/vector_test.cc @@ -16,6 +16,7 @@ #include <cstddef> +#include "pw_compilation_testing/negative_compilation.h" #include "pw_containers_private/test_helpers.h" #include "pw_unit_test/framework.h" @@ -655,29 +656,48 @@ TEST(Vector, ConstexprMaxSize) { EXPECT_EQ(vector.max_size(), vector2.max_size()); - // The following code would fail with the following compiler error: - // "non-type template argument is not a constant expression" - // Reason: the generic_vector doesn't return a constexpr max_size value. - // Vector<int>& generic_vector(vector); - // Vector<int, generic_vector.max_size()> vector3; +#if PW_NC_TEST(DynamicCapacity_MaxSizeNotConstexpr) + PW_NC_EXPECT_CLANG("non-type template argument is not a constant expression"); + PW_NC_EXPECT_GCC("call to non-'constexpr' function"); + Vector<int>& generic_vector(vector); + Vector<int, generic_vector.max_size()> vector3; +#endif // PW_NC_TEST +} + +TEST(Vector, DeleteAndDestructionDisallowedOnDynamicCapacity) { + std::byte raw_storage[64]{}; + Vector<int, 4>* vector = new (raw_storage) Vector<int, 4>; + [[maybe_unused]] Vector<int>* generic_vector = vector; + +#if PW_NC_TEST(GenericCapacity_DeleteDisallowed) + PW_NC_EXPECT(" protected "); + delete generic_vector; +#elif PW_NC_TEST(GenericCapacity_ManualDestructionDisallowed) + PW_NC_EXPECT(" protected "); + generic_vector->~Vector(); +#elif PW_NC_TEST(KnownCapacity_ManualDestructionDisallowed) + PW_NC_EXPECT(" protected "); + vector->~Vector<int>(); +#else + vector->~Vector<int, 4>(); +#endif // PW_NC_TEST } // Test that Vector<T> is trivially destructible when its type is. -static_assert(std::is_trivially_destructible_v<Vector<int>>); static_assert(std::is_trivially_destructible_v<Vector<int, 4>>); static_assert(std::is_trivially_destructible_v<MoveOnly>); -static_assert(std::is_trivially_destructible_v<Vector<MoveOnly>>); static_assert(std::is_trivially_destructible_v<Vector<MoveOnly, 1>>); static_assert(std::is_trivially_destructible_v<CopyOnly>); -static_assert(std::is_trivially_destructible_v<Vector<CopyOnly>>); static_assert(std::is_trivially_destructible_v<Vector<CopyOnly, 99>>); static_assert(!std::is_trivially_destructible_v<Counter>); -// NOTE: the size-polymorphic base class cannot be destructed directly. -static_assert(std::is_trivially_destructible_v<Vector<Counter>>); static_assert(!std::is_trivially_destructible_v<Vector<Counter, 99>>); +// Generic-capacity Vectors cannot be constructed or destructed. +static_assert(!std::is_constructible_v<Vector<int>>); +static_assert(!std::is_destructible_v<Vector<int>>); + } // namespace } // namespace pw |