[clang] 192be3c - fix: constexpr bit_cast with empty base classes (#82383)

via cfe-commits cfe-commits at lists.llvm.org
Sun Mar 17 09:35:17 PDT 2024


Author: sethp
Date: 2024-03-17T17:35:13+01:00
New Revision: 192be3c9c13363847d176f2c4bba2bd4be5e822f

URL: https://github.com/llvm/llvm-project/commit/192be3c9c13363847d176f2c4bba2bd4be5e822f
DIFF: https://github.com/llvm/llvm-project/commit/192be3c9c13363847d176f2c4bba2bd4be5e822f.diff

LOG: fix: constexpr bit_cast with empty base classes (#82383)

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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ba9de1ac98de08..125d51c42d507f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fa9e8ecf654378..80f49714b64f0f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -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);

diff  --git a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
index c5b8032f40b131..7520b43a194aba 100644
--- a/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-bit-cast.cpp
@@ -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;
     }
@@ -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() {


        


More information about the cfe-commits mailing list