Skip to content

Move construction clobbers data through [[no_unique_address]] #60711

@danakj

Description

@danakj

Godbolt: https://godbolt.org/z/e96axcv1b

#include <stdint.h>

#include <iostream>
#include <string>
#include <vector>

struct S2 {
    uint64_t a;
};

struct S : public S2 {
    S(uint8_t b, uint64_t a) : S2(a), b(b) {}
    uint8_t b;
    // 3 bytes padding.
};
static_assert(sizeof(S) == 16);

union U {
    U() {}
    [[no_unique_address]] S s;
};
static_assert(sizeof(U) == 16);

struct D {
    D(uint8_t i) : i(i) {}

    [[no_unique_address]] U u;
    uint8_t i;
};
static_assert(sizeof(D) == 16);

int main() {
    D d(1u);
    std::cout << (int)d.i << "\n";  // Prints 1

    // Regular construction into `D::u` doesn't touch `D::i`. Good.
    new (&d.u.s) S(2, 3);
    std::cout << (int)d.i << "\n";  // Prints 1

    S s(4, 5);
    // Move construction into `D::u` overwrites `D::i`. Bad.
    new (&d.u.s) S(std::move(s));
    std::cout << (int)d.i << "\n";  // Prints 0
    return d.i;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++20questionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions