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