Issue 136685
Summary [[msvc::no_unique_address]] differs in layout from MSVC ABI
Labels new issue
Assignees
Reporter Ext3h
    Consider the following examples:

```c++
#include <cstddef>

struct S1 {};
struct S2 {};

struct S3 {
    [[no_unique_address]] [[msvc::no_unique_address]] S1 s1;
};

struct ST1 {
    [[no_unique_address]] [[msvc::no_unique_address]] S3 s1;
    S1 s2;
};

struct ST2 {
 [[no_unique_address]] [[msvc::no_unique_address]] S3 s1;
    S2 s2;
};

struct ST3 {
    [[no_unique_address]] [[msvc::no_unique_address]] S3 s1;
    [[no_unique_address]] [[msvc::no_unique_address]] S1 s2;
};

struct ST4 {
 [[no_unique_address]] [[msvc::no_unique_address]] S3 s1;
 [[no_unique_address]] [[msvc::no_unique_address]] S2 s2;
};

static_assert(sizeof(ST1) == 2);

size_t size_st1() {
 return sizeof(ST1);
}

size_t offset_st1() {
    return offsetof(ST1, s2);
}

#ifdef _MSC_VER
static_assert(sizeof(ST2) == 2);
#else
static_assert(sizeof(ST2) == 1);
#endif

size_t size_st2() {
 return sizeof(ST2);
}

size_t offset_st2() {
    return offsetof(ST2, s2);
}

#ifdef _MSC_VER
static_assert(sizeof(ST3) == 1);
#else
static_assert(sizeof(ST3) == 2);
#endif

size_t size_st3() {
 return sizeof(ST3);
}

size_t offset_st3() {
    return offsetof(ST3, s2);
}

static_assert(sizeof(ST4) == 1);

size_t size_st4() {
 return sizeof(ST4);
}

size_t offset_st4() {
    return offsetof(ST4, s2);
}
```

Example output: https://godbolt.org/z/xnrT5Tsq1

For `ST4` the behavior of Clang and MSVC matches in all aspects, both compilers optimize to the expected extent.

For `ST1` the layout does match, but actually not for the same reasons. MSVC preserves `ST1::s1` as a unique address because of the unique sibling `ST1::s2`. Clang preserves `ST1::s1` because otherwise `ST1::s2` would alias `ST1::s1::s1`. And actually the output of ***neither*** compiler is optimized as far as you'd expect.

This difference then causes trouble in `ST2`. Clang applies the optimization as strict aliasing rules are applied, but MSVC doesn't.

In `ST3` we can see the opposite behavior. Even though everything is flagged with `[[msvc::no_unique_address]]`, Clang still tries to avoid aliasing of `ST1::s2` and `ST1::s1::s1`. MSVC does not.

See also https://github.com/microsoft/STL/issues/1364 for the epic depending on ABI equality.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to