diff options
author | Jan Kokemüller <jan.kokemueller@gmail.com> | 2024-01-22 15:05:39 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-22 09:05:39 -0500 |
commit | 4f4690530e8b40cdf3a17c76a352b26c2fb0446c (patch) | |
tree | c157c476049d6032b0a734ab92e73dbc6d6734e1 /libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp | |
parent | bf7b8dae0615884816fff54cac08bc691746b1ee (diff) | |
download | llvm-4f4690530e8b40cdf3a17c76a352b26c2fb0446c.zip llvm-4f4690530e8b40cdf3a17c76a352b26c2fb0446c.tar.gz llvm-4f4690530e8b40cdf3a17c76a352b26c2fb0446c.tar.bz2 |
[libc++] Ensure that std::expected has no tail padding (#69673)
Currently std::expected can have some padding bytes in its tail due to
[[no_unique_address]]. Those padding bytes can be used by other objects.
For example, in the current implementation:
sizeof(std::expected<std::optional<int>, bool>) ==
sizeof(std::expected<std::expected<std::optional<int>, bool>, bool>)
As a result, the data layout of an
std::expected<std::expected<std::optional<int>, bool>, bool>
can look like this:
+-- optional "has value" flag
| +--padding
/---int---\ | |
00 00 00 00 01 00 00 00
| |
| +- "outer" expected "has value" flag
|
+- expected "has value" flag
This is problematic because `emplace()`ing the "inner" expected can not
only overwrite the "inner" expected "has value" flag (issue #68552) but
also the tail padding where other objects might live.
This patch fixes the problem by ensuring that std::expected has no tail
padding, which is achieved by conditional usage of [[no_unique_address]]
based on the tail padding that this would create.
This is an ABI breaking change because the following property changes:
sizeof(std::expected<std::optional<int>, bool>) <
sizeof(std::expected<std::expected<std::optional<int>, bool>, bool>)
Before the change, this relation didn't hold. After the change, the relation
does hold, which means that the size of std::expected in these cases increases
after this patch. The data layout will change in the following cases where
tail padding can be reused by other objects:
class foo : std::expected<std::optional<int>, bool> {
bool b;
};
or using [[no_unique_address]]:
struct foo {
[[no_unique_address]] std::expected<std::optional<int>, bool> e;
bool b;
};
The vendor communication is handled in #70820.
Fixes: #70494
Co-authored-by: philnik777 <nikolasklauser@berlin.de>
Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
Diffstat (limited to 'libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp')
-rw-r--r-- | libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp b/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp index 84b57ae..ec55f63 100644 --- a/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp +++ b/libcxx/test/std/utilities/expected/expected.expected/monadic/transform_error.pass.cpp @@ -9,8 +9,8 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // GCC has a issue for `Guaranteed copy elision for potentially-overlapping non-static data members`, -// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333, but we have a workaround to -// avoid this issue. +// please refer to: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108333. +// XFAIL: gcc-13 // <expected> |