microsoft / microsoft/STL

`<type_traits>`: `aligned_storage` has incorrect alignment defaults

Open
#784 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug vNext
Dominant language
C++
Stars
11.2k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

[tab:meta.trans.other] specifies that default-alignment in

template<size_t Len, size_t Align = default-alignment>
struct aligned_storage;

"shall be the most stringent alignment requirement for any C++ object type whose size is no greater than Len". Since all valid alignments are powers of two, and the size of an object is always a multiple of its alignment, the default should be the largest power of two which divides Len evenly and is not greater than some upper bound. That upper bound is either alignof(max_align_t) (the largest fundamental alignment requirement) or some compiler-specific implementation limit on the largest possible alignment for an object type. I suspect the Standard intends the former, but I've asked LWG for clarification.

In any case, we should not be using alignof(max_align_t) as the default alignment for all sizes, which results in silliness like sizeof(aligned_storage<1>) == 8.

Command-line test case
(See https://godbolt.org/z/J7naDp)

C:\Users\Casey\Desktop>type repro.cpp
#include <cstddef>
#include <type_traits>
#include <utility>

using std::aligned_storage_t, std::index_sequence, std::max_align_t, std::size_t;

constexpr size_t alignment_for(size_t const Size) {
    for (size_t alignment = 1; alignment < alignof(max_align_t); alignment *= 2) {
        if (((alignment * 2 - 1) & Size) != 0) {
            return alignment;
        }
    }
    return alignof(max_align_t);
}

template <size_t Size>
constexpr void test_one() {
    static_assert(alignof(aligned_storage_t<Size>) == alignment_for(Size));
    static_assert(alignof(aligned_storage_t<Size>) != alignof(max_align_t));
    static_assert(sizeof(aligned_storage_t<Size>) == Size);
}

template <size_t... Sizes>
constexpr void test(index_sequence<Sizes...>) {
    (test_one<Sizes + 1>(), ...);
}

static_assert((test(std::make_index_sequence<alignof(max_align_t) - 1>{}), true));

static_assert(alignof(aligned_storage_t<2 * alignof(max_align_t)>) == alignof(max_align_t));

C:\Users\Casey\Desktop>cl /nologo /std:c++17 /permissive- repro.cpp
repro.cpp
repro.cpp(18): error C2607: static assertion failed
repro.cpp(24): note: see reference to function template instantiation 'void test_one<1>(void)' being compiled
repro.cpp(28): note: see reference to function template instantiation 'void test<0,1,2,3,4,5,6>(std::integer_sequence<size_t,0,1,2,3,4,5,6>)' being compiled
repro.cpp(28): note: while evaluating constexpr function 'test'
repro.cpp(19): error C2607: static assertion failed
repro.cpp(28): note: while evaluating constexpr function 'test'
repro.cpp(20): error C2607: static assertion failed
repro.cpp(28): note: while evaluating constexpr function 'test'

vNext note: Resolving this issue will require breaking binary compatibility. We won't be able to accept pull requests for this issue until the vNext branch is available. See #169 for more information.

Additional Context
Skipped libcxx test
https://github.com/microsoft/STL/blob/06827feb4cdc4d2328dfbfab9fd5302de6058dd9/tests/libcxx/expected_results.txt#L644-L645

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the <type_traits> aligned_storage implementation and the libcxx expectation entry at tests/libcxx/expected_results.txt#L644-L645; use the provided C++17 repro to confirm the current alignment and size behavior. Resolve the Standard/LWG question and vNext binary-compatibility constraint before changing behavior; done means the test is no longer skipped and the repro assertions pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.