https://github.com/Michael137 created 
https://github.com/llvm/llvm-project/pull/201102

Currently Clang's implementation of `__builtin_clear_padding` diverges from GCC 
in its treatment of unnamed bitfields.

GCC treats them as padding (which seems correct since they can't be named and 
wouldn't be part of the value representation of an object, though I'm not sure 
what the standard has to say about this).

[Gobdolt](https://godbolt.org/z/e9Mo91dhh)

GCC trunk:
```
pre-clear bytes:   ff ff ff ff
post-clear bytes:  01 00 00 80
b1 = 1, b2 = 1
```

Clang trunk:
```
pre-clear bytes:   ff ff ff ff
post-clear bytes:  ff ff ff ff
b1 = 1, b2 = 1
```

Note how we cleared the padding with GCC.

This patch skips marking unnamed bitfields as "occupied". The rest of the 
machinery works out-of-the-box.

>From 3e92fcb13a46c26f32f974fc088ccb3212231a41 Mon Sep 17 00:00:00 2001
From: Michael Buch <[email protected]>
Date: Tue, 2 Jun 2026 12:55:03 +0100
Subject: [PATCH] [clang] Treat unnamed bitfields as padding in
 `__builtin_clear_padding`

Currently Clang's implementation of `__builtin_clear_padding` diverges from GCC 
in its treatment of unnamed bitfields.

GCC treats them as padding (which seems correct since they can't be named and 
wouldn't be part of the value representation of an object, though I'm not sure 
what the standard has to say about this).

[Gobdolt](https://godbolt.org/z/e9Mo91dhh)

GCC trunk:
```
pre-clear bytes:   ff ff ff ff
post-clear bytes:  01 00 00 80
b1 = 1, b2 = 1
```

Clang trunk:
```
pre-clear bytes:   ff ff ff ff
post-clear bytes:  ff ff ff ff
b1 = 1, b2 = 1
```

Note how we cleared the padding with GCC.

This patch skips marking unnamed bitfields as "occupied". The rest of the 
machinery works out-of-the-box.
---
 clang/lib/CodeGen/CGBuiltin.cpp               |  4 ++++
 .../atomics/builtin_clear_padding.pass.cpp    | 20 +++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 50d34889d8dc1..40c6da27718bb 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2836,6 +2836,10 @@ struct PaddingClearer {
     }
 
     for (auto *Field : R->fields()) {
+      // Treat unnamed bitfields as padding.
+      if (Field->isUnnamedBitField())
+        continue;
+
       auto FieldOffset = ASTLayout.getFieldOffset(Field->getFieldIndex());
       if (Field->isBitField()) {
         OccuppiedIntervals.push_back(BitInterval{
diff --git a/libcxx/test/libcxx/atomics/builtin_clear_padding.pass.cpp 
b/libcxx/test/libcxx/atomics/builtin_clear_padding.pass.cpp
index 32bcd376cdcf9..6b10e7bea5751 100644
--- a/libcxx/test/libcxx/atomics/builtin_clear_padding.pass.cpp
+++ b/libcxx/test/libcxx/atomics/builtin_clear_padding.pass.cpp
@@ -656,6 +656,26 @@ void structTests() {
     assert(memcmp(&s1, &s2, sizeof(S)) == 0);
   }
 
+  // unnamed bit fields
+  {
+    struct S {
+      unsigned int b1 : 1;
+      unsigned int : 30;
+      unsigned int b2 : 1;
+    };
+
+    S s1, s2;
+    memset(&s1, 0, sizeof(S));
+    memset(&s2, 42, sizeof(S));
+
+    s1.b1 = 1;
+    s1.b2 = 1;
+    s2.b1 = 1;
+    s2.b2 = 1;
+    __builtin_clear_padding(&s2);
+    assert(memcmp(&s1, &s2, sizeof(S)) == 0);
+  }
+
   testAllStructsForType<32, 16, char>(11, 22, 33, 44);
   testAllStructsForType<64, 32, char>(4, 5, 6, 7);
   testAllStructsForType<32, 16, volatile char>(11, 22, 33, 44);

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to