3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 14:13:23 +00:00

vector.h: add assert to fail compilation if alignment isn't ok

let's see if all buildbots are happy with this..
This commit is contained in:
Nuno Lopes 2021-05-23 15:57:56 +01:00
parent 8fd7226b6f
commit aef38099bf

View file

@ -163,14 +163,10 @@ template<typename T, bool CallDestructors=true, typename SZ = unsigned>
class vector { class vector {
#define SIZE_IDX -1 #define SIZE_IDX -1
#define CAPACITY_IDX -2 #define CAPACITY_IDX -2
T * m_data; T * m_data = nullptr;
void destroy_elements() { void destroy_elements() {
iterator it = begin(); std::destroy_n(m_data, size());
iterator e = end();
for (; it != e; ++it) {
it->~T();
}
} }
void free_memory() { void free_memory() {
@ -178,17 +174,21 @@ class vector {
} }
void expand_vector() { void expand_vector() {
// ensure that the data is sufficiently aligned
// better fail to compile than produce code that may crash
static_assert((sizeof(SZ) * 2) % alignof(T) == 0);
if (m_data == nullptr) { if (m_data == nullptr) {
SZ capacity = 2; SZ capacity = 2;
SZ * mem = reinterpret_cast<SZ*>(memory::allocate(sizeof(T) * capacity + sizeof(SZ) * 2)); SZ * mem = reinterpret_cast<SZ*>(memory::allocate(sizeof(T) * capacity + sizeof(SZ) * 2));
*mem = capacity; *mem = capacity;
mem++; mem++;
*mem = 0; *mem = 0;
mem++; mem++;
m_data = reinterpret_cast<T *>(mem); m_data = reinterpret_cast<T *>(mem);
} }
else { else {
static_assert(std::is_nothrow_move_constructible<T>::value, ""); static_assert(std::is_nothrow_move_constructible<T>::value);
SASSERT(capacity() > 0); SASSERT(capacity() > 0);
SZ old_capacity = reinterpret_cast<SZ *>(m_data)[CAPACITY_IDX]; SZ old_capacity = reinterpret_cast<SZ *>(m_data)[CAPACITY_IDX];
SZ old_capacity_T = sizeof(T) * old_capacity + sizeof(SZ) * 2; SZ old_capacity_T = sizeof(T) * old_capacity + sizeof(SZ) * 2;
@ -203,15 +203,12 @@ class vector {
m_data = reinterpret_cast<T *>(mem + 2); m_data = reinterpret_cast<T *>(mem + 2);
} else { } else {
mem = (SZ*)memory::allocate(new_capacity_T); mem = (SZ*)memory::allocate(new_capacity_T);
auto old_data = m_data;
auto old_size = size(); auto old_size = size();
mem[1] = old_size; mem[1] = old_size;
m_data = reinterpret_cast<T *>(mem + 2); auto new_data = reinterpret_cast<T *>(mem + 2);
for (unsigned i = 0; i < old_size; ++i) { std::uninitialized_move_n(m_data, old_size, new_data);
new (&m_data[i]) T(std::move(old_data[i])); destroy();
old_data[i].~T(); m_data = new_data;
}
memory::deallocate(old_mem);
} }
*mem = new_capacity; *mem = new_capacity;
} }
@ -243,12 +240,9 @@ public:
typedef T * iterator; typedef T * iterator;
typedef const T * const_iterator; typedef const T * const_iterator;
vector(): vector() = default;
m_data(nullptr) {
}
vector(SZ s) { vector(SZ s) {
m_data = nullptr;
init(s); init(s);
} }
@ -271,25 +265,22 @@ public:
} }
} }
vector(SZ s, T const & elem): vector(SZ s, T const & elem) {
m_data(nullptr) {
resize(s, elem); resize(s, elem);
} }
vector(vector const & source): vector(vector const & source) {
m_data(nullptr) {
if (source.m_data) { if (source.m_data) {
copy_core(source); copy_core(source);
} }
SASSERT(size() == source.size()); SASSERT(size() == source.size());
} }
vector(vector&& other) noexcept : m_data(nullptr) { vector(vector&& other) noexcept {
std::swap(m_data, other.m_data); std::swap(m_data, other.m_data);
} }
vector(SZ s, T const * data): vector(SZ s, T const * data) {
m_data(nullptr) {
for (SZ i = 0; i < s; i++) { for (SZ i = 0; i < s; i++) {
push_back(data[i]); push_back(data[i]);
} }
@ -321,7 +312,6 @@ public:
bool operator!=(vector const & other) const { bool operator!=(vector const & other) const {
return !(*this == other); return !(*this == other);
} }
vector & operator=(vector const & source) { vector & operator=(vector const & source) {
if (this == &source) { if (this == &source) {