Skip to content

Fix capacity of VLA moves with unequal allocators - #208

Merged
thirtytwobits merged 5 commits into
codex/fix-vla-allocator-move-noexceptfrom
codex/fix-vla-allocator-move-capacity
Oct 5, 2026
Merged

thirtytwobits merged 5 commits into
codex/fix-vla-allocator-move-noexceptfrom
codex/fix-vla-allocator-move-capacity

Conversation

@thirtytwobits

Copy link
Copy Markdown
Member

Moving a VLA with an unequal allocator allocates only the source's occupied storage but records the source's full capacity. Spare capacity is therefore reported as usable memory even though it was never allocated, permitting out-of-bounds appends and incorrect deallocation counts. An empty source with reserved capacity can produce a destination with null storage and nonzero capacity.

Record the allocated element count as the destination capacity in the unequal-allocator path. Equal-allocator moves continue transferring the original allocation and capacity. The shared fix covers both generic VLA elements and packed bool storage.

Add six regression tests covering nonempty and empty sources with spare capacity, growth beyond the destination allocation, allocator ownership and deallocation counts, source reuse, and equal-allocator capacity transfer for both int and bool.

Closes #205.

Stacked on #207. This PR targets codex/fix-vla-allocator-move-noexcept, so its diff contains only the capacity fix and its tests. Merge #207 first, then retarget this PR to main.

Validation:

  • Four regression cases fail before the fix; all six pass after it.
  • All eight VLA suites pass in C++14 under GCC 13.4 and Clang 22.1.8, in Debug and exceptions-disabled ReleaseEP configurations, with existing compiler/platform skips retained.
  • The new test suite passes C++17, C++20, and C++23 compilation under GCC and Clang, with exceptions enabled and disabled.
  • The six focused tests pass with Clang AddressSanitizer and UndefinedBehaviorSanitizer.
  • The original reproducer now reports size=3 capacity=3 allocated=3, with no deallocation-count mismatch.
  • Formatting and git diff --check pass.

The head commit includes the documented #verification trigger so the verification workflow also runs while this PR targets another codex/ branch.

@thirtytwobits
thirtytwobits added this pull request to stack #210 September 29, 2026 21:11
@thirtytwobits
thirtytwobits force-pushed the codex/fix-vla-allocator-move-capacity branch from 56170c7 to 1ffbeae Compare October 1, 2026 17:05
@thirtytwobits
thirtytwobits requested a balanced review from Copilot October 1, 2026 17:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The focused fix aligns capacity with allocation size and is comprehensively covered by relevant regression tests.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes unequal-allocator VLA moves so reported capacity matches allocated storage for generic and packed-bool elements.

Changes:

  • Records destination capacity using the source’s occupied storage.
  • Adds six typed regression cases covering allocator ownership, growth, empty sources, reuse, and equal allocators.
  • Registers the new test suite.
File Description
include/​cetl/​variable_length_array.hpp Corrects unequal-allocator move capacity bookkeeping.
cetlvast/​suites/​unittest/​test_variable_length_array_move_capacity.cpp Adds int and bool regression coverage.
cetlvast/​suites/​unittest/​CMakeLists.txt Includes the new tests in native suites.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

thirtytwobits and others added 2 commits October 1, 2026 12:43
Adding tests that properly cover move and copy construction of VLA when using allocators.
Allocator-extended construction:
- Selecting the allocator-extended move constructor overload, and its
  noexcept specification, now depends only on
  allocator_traits::is_always_equal. propagate_on_container_move_assignment
  has no bearing on construction. With a possibly unequal allocator the
  constructor may have to allocate and so may throw.
- The allocator-extended copy and move constructors now use the given
  allocator as-is. select_on_container_copy_construction is applied only
  in the plain copy constructor of VariableLengthArray and its bool
  specialization, matching std::vector.

Assignment:
- move_assign_from now moves rhs.alloc_ into move_assign_alloc instead of
  copying it. The static_assert message now says "move assign" instead of
  "copy".
- VariableLengthArrayBase explicitly deletes its copy constructor and its
  copy and move assignment operators. These go through the extended
  constructor and copy_assign_from/move_assign_from, which need the
  derived class's max_size().

Namespace:
- VariableLengthArrayBase is now in cetl::detail to mark it as an
  implementation detail. No cetlvast sources named it directly.

Tests:
- test_variable_length_array_compiles now expects a VLA whose allocator
  has POCMA but is not always-equal to have a potentially-throwing
  allocator-extended move constructor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thirtytwobits and others added 2 commits October 1, 2026 14:41
MoveConstructWithNewAllocatorExceptionSpecification also runs against
std::vector as a reference. It required vector(vector&&, const Allocator&)
to be noexcept exactly when is_always_equal is true. The standard doesn't
specify noexcept for that constructor: libstdc++ makes it conditional on
is_always_equal, but libc++ never marks it noexcept, so the test failed in
every clang-native CI job.

The VLA instantiations still require the exact rule. For std::vector the
test now checks only that it is noexcept when the allocator is always
equal, which holds for both standard libraries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…xcept' into codex/fix-vla-allocator-move-capacity

# Conflicts:
#	include/cetl/variable_length_array.hpp
@thirtytwobits
thirtytwobits merged commit 45f61dd into main Oct 5, 2026
24 checks passed
@thirtytwobits
thirtytwobits deleted the codex/fix-vla-allocator-move-capacity branch October 5, 2026 21:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

VLA unequal-allocator move constructor records source capacity for a smaller allocation

3 participants