Skip to content

Commit 5fdbb44

Browse files
committed
[NFC] Add test where the padding of a [[no_unique_address]] field with a custom type is reused
1 parent 9b0ab90 commit 5fdbb44

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

test/Interop/Cxx/class/Inputs/member-variables.h

+20
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define TEST_INTEROP_CXX_CLASS_INPUTS_MEMBER_VARIABLES_H
33

44
#include <cstddef>
5+
#include <type_traits>
56
#include <optional>
67

78
class MyClass {
@@ -46,6 +47,25 @@ struct ReuseOptionalFieldPaddingWithTypedef {
4647
int offset() const { return offsetof(ReuseOptionalFieldPadding, c); }
4748
};
4849

50+
// Using a mix of private and public fields prevents this class from being
51+
// standard-layout, which is necessary to allow clang to reuse its padding.
52+
template<typename T>
53+
struct NonStandardLayoutClass {
54+
private:
55+
T x;
56+
public:
57+
char pad_me;
58+
};
59+
static_assert(std::is_standard_layout_v<NonStandardLayoutClass<int>> == false);
60+
61+
struct ReuseNonStandardLayoutFieldPadding {
62+
[[no_unique_address]] NonStandardLayoutClass<int> a;
63+
char c;
64+
char get_c() const { return c; }
65+
void set_c(char c) { this->c = c; }
66+
// C-style implementation of offsetof() to avoid non-standard-layout warning
67+
int offset() const { return (char *) &this->c - (char *) this; }
68+
};
4969

5070
inline int takesZeroSizedInCpp(HasZeroSizedField x) {
5171
return x.a;

test/Interop/Cxx/class/zero-sized-field.swift

+14
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,18 @@ FieldsTestSuite.test("Typedef'd optional field padding reused") {
5454
expectEqual(s2.get_c(), 6)
5555
}
5656

57+
FieldsTestSuite.test("Non-standard-layout field padding reused") {
58+
var s = ReuseNonStandardLayoutFieldPadding()
59+
s.c = 5
60+
expectEqual(Int(s.offset()), MemoryLayout<ReuseNonStandardLayoutFieldPadding>.offset(of: \.c)!)
61+
expectEqual(s.c, 5)
62+
expectEqual(s.get_c(), 5)
63+
s.set_c(6)
64+
expectEqual(s.c, 6)
65+
expectEqual(s.get_c(), 6)
66+
let s2 = s
67+
expectEqual(s2.c, 6)
68+
expectEqual(s2.get_c(), 6)
69+
}
70+
5771
runAllTests()

0 commit comments

Comments
 (0)