Skip to content

Commit

Permalink
fix: constexpr bit_cast with empty base classes (#82383)
Browse files Browse the repository at this point in the history
Prior to this commit, clang would fail to produce a constant value for
`b` in:

```c++
struct base {
};

struct s : base {
    int z;
};

constexpr auto b = std::bit_cast<s>(0x12); 
```

e.g. https://godbolt.org/z/srrbTMPq4
  • Loading branch information
sethp committed Mar 17, 2024
1 parent d39ac3a commit 192be3c
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 4 deletions.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ Bug Fixes to C++ Support
Fixes (#GH84368).
- Fixed a crash while checking constraints of a trailing requires-expression of a lambda, that the
expression references to an entity declared outside of the lambda. (#GH64808)
- Clang's __builtin_bit_cast will now produce a constant value for records with empty bases. See:
(#GH82383)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7347,9 +7347,6 @@ class BufferToAPValueConverter {
for (size_t I = 0, E = CXXRD->getNumBases(); I != E; ++I) {
const CXXBaseSpecifier &BS = CXXRD->bases_begin()[I];
CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl();
if (BaseDecl->isEmpty() ||
Info.Ctx.getASTRecordLayout(BaseDecl).getNonVirtualSize().isZero())
continue;

std::optional<APValue> SubObj = visitType(
BS.getType(), Layout.getBaseClassOffset(BaseDecl) + Offset);
Expand Down
6 changes: 5 additions & 1 deletion clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ void test_record() {
struct tuple4 {
unsigned x, y, z, doublez;

constexpr bool operator==(tuple4 const &other) const {
bool operator==(tuple4 const &other) const = default;
constexpr bool operator==(bases const &other) const {
return x == other.x && y == other.y &&
z == other.z && doublez == other.doublez;
}
Expand All @@ -99,6 +100,9 @@ void test_record() {
constexpr tuple4 t4 = bit_cast<tuple4>(b);
static_assert(t4 == tuple4{1, 2, 3, 4});
static_assert(round_trip<tuple4>(b));

constexpr auto b2 = bit_cast<bases>(t4);
static_assert(t4 == b2);
}

void test_partially_initialized() {
Expand Down

0 comments on commit 192be3c

Please sign in to comment.