Repository navigation
Conversation
vector declared its inline buffer as `T _inline_buffer[N]`, so the compiler default-constructed every inline element and destroyed all of them again after ~vector() had already destroyed the live ones. Once the vector grew past its inline capacity, the elements were memcpy'd to the heap but the stale copies left in the inline buffer were still destroyed. For the `cf_ptr<IAGSubgraphRef>` stack in Subgraph::update() this released up to 32 subgraphs an extra time whenever more than 32 subgraphs were pending, eventually freeing subgraphs that were still in use. Store inline elements in raw, aligned storage so their lifetime is managed solely by the vector. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> # Conflicts: # Sources/ComputeCxx/Vector/Vector.h
Also remove the redundant `*&` from the other element accessors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rage shrink_to_fit() on a vector with no inline capacity always reallocated to zero elements, freeing the buffer even when it still held elements. Shrink to the current size instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The move assignment operator called `~T()` on each unique_ptr element, where T is the pointee type, which fails to compile once instantiated. Reset the elements instead, matching the destructor. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…'ing them Growing or shrinking a vector relocated elements with memcpy/realloc regardless of their type, bypassing their move constructors and destructors. Like llvm::SmallVector, only use memcpy/realloc for trivially copyable elements, and otherwise move each element into the new buffer and destroy the original. Compare::Enum was non-movable but stored in a growable vector, so give it a move constructor that transfers ownership of its copies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Grow to at least 2 * capacity + 1 instead of 1.5 * capacity, computing the new capacity in integer arithmetic and reporting overflow of size_type instead of silently truncating. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lements insert() move-assigned into the uninitialized slot past the end, then placement-constructed the value over a live, moved-from element without destroying it. erase() destroyed the erased elements and then swapped live elements with them. Like llvm::SmallVector, insert() now move-constructs the new last element, shifts the rest with move assignment and assigns the value, and erase() move-assigns the tail down before destroying the leftover elements. Inserting at the end goes through push_back(), which also avoids reading back() of an empty vector. erase() still returns the new end() rather than the iterator following the erased elements, since Graph::invalidate_subgraphs() relies on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use std::destroy and the uninitialized memory algorithms for element lifetimes in the destructor, move operations, clear(), pop_back() and resize(), and only reserve in resize() when growing. Like llvm::SmallVector, moving from a vector with inline elements into a vector that has a heap buffer now keeps that buffer rather than freeing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
push_back(), insert(), resize(count, value) and emplace_back() read their argument after growing the vector, so passing an element of the same vector (e.g. `v.push_back(v[0])` when full) read from the freed buffer. insert() could also read the argument after shifting it. Like llvm::SmallVector, recompute the argument's address after growing when it refers to the vector's storage, and adjust it if insert() shifted it. emplace_back() constructs the new element before growing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both were declared by the unique_ptr specialization but never defined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It was declared by the unique_ptr specialization but never defined. Implemented like the other specializations, following llvm::SmallVector. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It was declared by the unique_ptr specialization but never defined. New elements are value-initialized to nullptr. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It was declared by the unique_ptr specialization but never defined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
insert() and resize() taking a `const std::unique_ptr &` were declared but never defined, and can't be, since unique_ptr is not copyable. Mark them deleted like push_back(const std::unique_ptr &), so that misuse is a compile error rather than a link error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jcmosc
force-pushed
the
rewrite-vector
branch
from
October 22, 2026 16:27
0c9eb5c to
d26179c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.