Skip to content

Commit 5c24c31

Browse files
authored
[clang] Implement CWG2759 "[[no_unique_address] and common initial sequence" (#82607)
This patch implements said defect report resolution by adding additional check to common initial sequence evaluation. Consequently, this fixes CWG2759.
1 parent da1880c commit 5c24c31

File tree

6 files changed

+128
-15
lines changed

6 files changed

+128
-15
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@ C++20 Feature Support
8383

8484
- Implemented the `__is_layout_compatible` intrinsic to support
8585
`P0466R5: Layout-compatibility and Pointer-interconvertibility Traits <https://wg21.link/P0466R5>`_.
86-
Note: `CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_
87-
is not yet implemented.
8886

8987
C++23 Feature Support
9088
^^^^^^^^^^^^^^^^^^^^^
@@ -108,6 +106,10 @@ Resolutions to C++ Defect Reports
108106
of two types.
109107
(`CWG1719: Layout compatibility and cv-qualification revisited <https://cplusplus.github.io/CWG/issues/1719.html>`_).
110108

109+
- ``[[no_unique_address]]`` is now respected when evaluating layout
110+
compatibility of two types.
111+
(`CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_).
112+
111113
C Language Changes
112114
------------------
113115

clang/lib/Sema/SemaChecking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19036,6 +19036,9 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
1903619036
return false;
1903719037
}
1903819038

19039+
if (Field1->hasAttr<clang::NoUniqueAddressAttr>() ||
19040+
Field2->hasAttr<clang::NoUniqueAddressAttr>())
19041+
return false;
1903919042
return true;
1904019043
}
1904119044

clang/test/CXX/drs/dr27xx.cpp

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,98 @@
1-
// RUN: %clang_cc1 -std=c++98 -verify=expected %s
2-
// RUN: %clang_cc1 -std=c++11 -verify=expected %s
3-
// RUN: %clang_cc1 -std=c++14 -verify=expected %s
4-
// RUN: %clang_cc1 -std=c++17 -verify=expected %s
5-
// RUN: %clang_cc1 -std=c++20 -verify=expected %s
6-
// RUN: %clang_cc1 -std=c++23 -verify=expected,since-cxx23 %s
7-
// RUN: %clang_cc1 -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s
1+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -verify=expected %s
2+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -verify=expected %s
3+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -verify=expected %s
4+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -verify=expected %s
5+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -verify=expected %s
6+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -verify=expected,since-cxx23 %s
7+
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s
88

99
#if __cplusplus <= 202002L
1010
// expected-no-diagnostics
1111
#endif
1212

13+
namespace dr2759 { // dr2759: 19
14+
#if __cplusplus >= 201103L
15+
16+
struct CStruct {
17+
int one;
18+
int two;
19+
};
20+
21+
struct CEmptyStruct {};
22+
struct CEmptyStruct2 {};
23+
24+
struct CStructNoUniqueAddress {
25+
int one;
26+
[[no_unique_address]] int two;
27+
};
28+
29+
struct CStructNoUniqueAddress2 {
30+
int one;
31+
[[no_unique_address]] int two;
32+
};
33+
34+
union UnionLayout {
35+
int a;
36+
double b;
37+
CStruct c;
38+
[[no_unique_address]] CEmptyStruct d;
39+
[[no_unique_address]] CEmptyStruct2 e;
40+
};
41+
42+
union UnionLayout2 {
43+
CStruct c;
44+
int a;
45+
CEmptyStruct2 e;
46+
double b;
47+
[[no_unique_address]] CEmptyStruct d;
48+
};
49+
50+
union UnionLayout3 {
51+
CStruct c;
52+
int a;
53+
double b;
54+
[[no_unique_address]] CEmptyStruct d;
55+
};
56+
57+
struct StructWithAnonUnion {
58+
union {
59+
int a;
60+
double b;
61+
CStruct c;
62+
[[no_unique_address]] CEmptyStruct d;
63+
[[no_unique_address]] CEmptyStruct2 e;
64+
};
65+
};
66+
67+
struct StructWithAnonUnion2 {
68+
union {
69+
CStruct c;
70+
int a;
71+
CEmptyStruct2 e;
72+
double b;
73+
[[no_unique_address]] CEmptyStruct d;
74+
};
75+
};
76+
77+
struct StructWithAnonUnion3 {
78+
union {
79+
CStruct c;
80+
int a;
81+
CEmptyStruct2 e;
82+
double b;
83+
[[no_unique_address]] CEmptyStruct d;
84+
} u;
85+
};
86+
87+
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
88+
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
89+
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
90+
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
91+
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
92+
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
93+
#endif
94+
} // namespace dr2759
95+
1396
namespace dr2789 { // dr2789: 18
1497
#if __cplusplus >= 202302L
1598
template <typename T = int>

clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,28 @@ struct [[msvc::no_unique_address]] S { // expected-error {{only applies to non-b
1717

1818
int [[msvc::no_unique_address]] c; // expected-error {{cannot be applied to types}} unsupported-error {{cannot be applied to types}}
1919
};
20+
21+
struct CStructNoUniqueAddress {
22+
int one;
23+
[[no_unique_address]] int two;
24+
// expected-warning@-1 {{unknown attribute 'no_unique_address' ignored}}
25+
};
26+
27+
struct CStructMSVCNoUniqueAddress {
28+
int one;
29+
[[msvc::no_unique_address]] int two;
30+
// unsupported-warning@-1 {{unknown attribute 'no_unique_address' ignored}}
31+
};
32+
33+
struct CStructMSVCNoUniqueAddress2 {
34+
int one;
35+
[[msvc::no_unique_address]] int two;
36+
// unsupported-warning@-1 {{unknown attribute 'no_unique_address' ignored}}
37+
};
38+
39+
static_assert(__has_cpp_attribute(no_unique_address) == 0);
40+
// unsupported-error@-1 {{static assertion failed due to requirement '201803L == 0'}}
41+
static_assert(!__is_layout_compatible(CStructNoUniqueAddress, CStructMSVCNoUniqueAddress), "");
42+
static_assert(__is_layout_compatible(CStructMSVCNoUniqueAddress, CStructMSVCNoUniqueAddress), "");
43+
static_assert(!__is_layout_compatible(CStructMSVCNoUniqueAddress, CStructMSVCNoUniqueAddress2), "");
44+
// unsupported-error@-1 {{static assertion failed due to requirement '!__is_layout_compatible(CStructMSVCNoUniqueAddress, CStructMSVCNoUniqueAddress2)':}}

clang/test/SemaCXX/type-traits.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,8 +1768,8 @@ void is_layout_compatible(int n)
17681768
static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), "");
17691769
static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), "");
17701770
static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
1771-
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) == bool(__has_cpp_attribute(no_unique_address)), ""); // FIXME: this is CWG2759
1772-
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) == bool(__has_cpp_attribute(no_unique_address)), ""); // FIXME: this is CWG2759
1771+
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
1772+
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
17731773
static_assert(__is_layout_compatible(CStruct, CStructAlignment), "");
17741774
static_assert(__is_layout_compatible(CStruct, CStructAlignedMembers), ""); // FIXME: alignment of members impact common initial sequence
17751775
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), "");
@@ -1782,10 +1782,10 @@ void is_layout_compatible(int n)
17821782
static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)), "");
17831783
static_assert(__is_layout_compatible(CStructNested, CStructNested2), "");
17841784
static_assert(__is_layout_compatible(UnionLayout, UnionLayout), "");
1785-
static_assert(__is_layout_compatible(UnionLayout, UnionLayout2), "");
1785+
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
17861786
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
1787-
static_assert(__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
1788-
static_assert(__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
1787+
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
1788+
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
17891789
static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), "");
17901790
static_assert(__is_layout_compatible(EnumForward, EnumForward), "");
17911791
static_assert(__is_layout_compatible(EnumForward, EnumClassForward), "");

clang/www/cxx_dr_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16362,7 +16362,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
1636216362
<td><a href="https://cplusplus.github.io/CWG/issues/2759.html">2759</a></td>
1636316363
<td>DR</td>
1636416364
<td>[[no_unique_address] and common initial sequence</td>
16365-
<td class="unknown" align="center">Unknown</td>
16365+
<td class="unreleased" align="center">Clang 19</td>
1636616366
</tr>
1636716367
<tr id="2760">
1636816368
<td><a href="https://cplusplus.github.io/CWG/issues/2760.html">2760</a></td>

0 commit comments

Comments
 (0)