Utils: Improve union layout

It is undefined behavior to access a uninitialized part of a union but
in this case it is not because both member have the same start member.
ControlBlock is in both at the address with the same layout and so it is
allowed by the C++ standard.

Change-Id: I3a165f67030d6726d2cb0cfbcbfb2622bcf7dcc4
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2023-09-09 11:53:32 +02:00
parent 6744c8e081
commit 6c17805ddc
2 changed files with 23 additions and 14 deletions

View File

@@ -425,7 +425,10 @@ public:
size_type newSize = oldSize + string.size();
reserve(optimalCapacity(newSize));
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wunsafe-buffer-usage")
std::char_traits<char>::copy(data() + oldSize, string.data(), string.size());
QT_WARNING_POP
setSize(newSize);
}

View File

@@ -11,6 +11,10 @@
#include <memory>
#include <type_traits>
QT_WARNING_PUSH
QT_WARNING_DISABLE_CLANG("-Wgnu-anonymous-struct")
QT_WARNING_DISABLE_CLANG("-Wnested-anon-types")
namespace Utils {
namespace Internal {
@@ -82,7 +86,7 @@ struct alignas(16) StringDataLayout
constexpr StringDataLayout() noexcept { reset(); }
constexpr StringDataLayout(const char *string, size_type size) noexcept
: control{0, true, true}
: controlReference{0, true, true}
, reference{{string}, size, 0}
{}
@@ -130,18 +134,18 @@ struct alignas(16) StringDataLayout
#endif
}
#pragma pack(push)
#pragma pack(1)
ControlBlock<MaximumShortStringDataAreaSize> control;
union {
char shortString[MaximumShortStringDataAreaSize];
struct
{
char dummy[sizeof(void *) - sizeof(ControlBlock<MaximumShortStringDataAreaSize>)];
ControlBlock<MaximumShortStringDataAreaSize> control;
char shortString[MaximumShortStringDataAreaSize];
};
struct
{
ControlBlock<MaximumShortStringDataAreaSize> controlReference;
ReferenceLayout reference;
};
};
#pragma pack(pop)
};
template<uint MaximumShortStringDataAreaSize>
@@ -158,7 +162,7 @@ struct alignas(16) StringDataLayout<MaximumShortStringDataAreaSize,
constexpr StringDataLayout() noexcept { reset(); }
constexpr StringDataLayout(const char *string, size_type size) noexcept
: control{0, true, true}
: controlReference{0, true, true}
, reference{{string}, size, 0}
{}
@@ -223,19 +227,21 @@ struct alignas(16) StringDataLayout<MaximumShortStringDataAreaSize,
#endif
}
#pragma pack(push)
#pragma pack(1)
ControlBlock<MaximumShortStringDataAreaSize> control;
union {
char shortString[MaximumShortStringDataAreaSize];
struct
{
char dummy[sizeof(void *) - sizeof(ControlBlock<MaximumShortStringDataAreaSize>)];
ControlBlock<MaximumShortStringDataAreaSize> control;
char shortString[MaximumShortStringDataAreaSize];
};
struct
{
ControlBlock<MaximumShortStringDataAreaSize> controlReference;
ReferenceLayout reference;
};
};
#pragma pack(pop)
};
} // namespace Internal
} // namespace Utils
QT_WARNING_POP