llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Michael Buch (Michael137)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/201102.diff


2 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+4) 
- (modified) libcxx/test/libcxx/atomics/builtin_clear_padding.pass.cpp (+20) 


``````````diff
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);

``````````

</details>


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

Reply via email to