aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pw_bluetooth/public/pw_bluetooth/gatt/client.h3
-rw-r--r--pw_containers/BUILD.bazel1
-rw-r--r--pw_containers/BUILD.gn2
-rw-r--r--pw_containers/CMakeLists.txt1
-rw-r--r--pw_containers/public/pw_containers/vector.h14
-rw-r--r--pw_containers/vector_test.cc40
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