Skip to content

[clang] Implement CWG2759 "[[no_unique_address] and common initial sequence" #82607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ C++20 Feature Support

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

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

- ``[[no_unique_address]]`` is now respected when evaluating layout
compatibility of two types.
(`CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_).

C Language Changes
------------------

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19033,6 +19033,9 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
return false;
}

if (Field1->hasAttr<clang::NoUniqueAddressAttr>() ||
Field2->hasAttr<clang::NoUniqueAddressAttr>())
return false;
return true;
}

Expand Down
97 changes: 90 additions & 7 deletions clang/test/CXX/drs/dr27xx.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,98 @@
// RUN: %clang_cc1 -std=c++98 -verify=expected %s
// RUN: %clang_cc1 -std=c++11 -verify=expected %s
// RUN: %clang_cc1 -std=c++14 -verify=expected %s
// RUN: %clang_cc1 -std=c++17 -verify=expected %s
// RUN: %clang_cc1 -std=c++20 -verify=expected %s
// RUN: %clang_cc1 -std=c++23 -verify=expected,since-cxx23 %s
// RUN: %clang_cc1 -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++98 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++11 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++14 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 -verify=expected %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++23 -verify=expected,since-cxx23 %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++2c -verify=expected,since-cxx23,since-cxx26 %s

#if __cplusplus <= 202002L
// expected-no-diagnostics
#endif

namespace dr2759 { // dr2759: 19
#if __cplusplus >= 201103L

struct CStruct {
int one;
int two;
};

struct CEmptyStruct {};
struct CEmptyStruct2 {};

struct CStructNoUniqueAddress {
int one;
[[no_unique_address]] int two;
};

struct CStructNoUniqueAddress2 {
int one;
[[no_unique_address]] int two;
};

union UnionLayout {
int a;
double b;
CStruct c;
[[no_unique_address]] CEmptyStruct d;
[[no_unique_address]] CEmptyStruct2 e;
};

union UnionLayout2 {
CStruct c;
int a;
CEmptyStruct2 e;
double b;
[[no_unique_address]] CEmptyStruct d;
};

union UnionLayout3 {
CStruct c;
int a;
double b;
[[no_unique_address]] CEmptyStruct d;
};

struct StructWithAnonUnion {
union {
int a;
double b;
CStruct c;
[[no_unique_address]] CEmptyStruct d;
[[no_unique_address]] CEmptyStruct2 e;
};
};

struct StructWithAnonUnion2 {
union {
CStruct c;
int a;
CEmptyStruct2 e;
double b;
[[no_unique_address]] CEmptyStruct d;
};
};

struct StructWithAnonUnion3 {
union {
CStruct c;
int a;
CEmptyStruct2 e;
double b;
[[no_unique_address]] CEmptyStruct d;
} u;
};

static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
#endif
} // namespace dr2759

namespace dr2789 { // dr2789: 18
#if __cplusplus >= 202302L
template <typename T = int>
Expand Down
25 changes: 25 additions & 0 deletions clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,28 @@ struct [[msvc::no_unique_address]] S { // expected-error {{only applies to non-b

int [[msvc::no_unique_address]] c; // expected-error {{cannot be applied to types}} unsupported-error {{cannot be applied to types}}
};

struct CStructNoUniqueAddress {
int one;
[[no_unique_address]] int two;
// expected-warning@-1 {{unknown attribute 'no_unique_address' ignored}}
};

struct CStructMSVCNoUniqueAddress {
int one;
[[msvc::no_unique_address]] int two;
// unsupported-warning@-1 {{unknown attribute 'no_unique_address' ignored}}
};

struct CStructMSVCNoUniqueAddress2 {
int one;
[[msvc::no_unique_address]] int two;
// unsupported-warning@-1 {{unknown attribute 'no_unique_address' ignored}}
};

static_assert(__has_cpp_attribute(no_unique_address) == 0);
// unsupported-error@-1 {{static assertion failed due to requirement '201803L == 0'}}
static_assert(!__is_layout_compatible(CStructNoUniqueAddress, CStructMSVCNoUniqueAddress), "");
static_assert(__is_layout_compatible(CStructMSVCNoUniqueAddress, CStructMSVCNoUniqueAddress), "");
static_assert(!__is_layout_compatible(CStructMSVCNoUniqueAddress, CStructMSVCNoUniqueAddress2), "");
// unsupported-error@-1 {{static assertion failed due to requirement '!__is_layout_compatible(CStructMSVCNoUniqueAddress, CStructMSVCNoUniqueAddress2)':}}
10 changes: 5 additions & 5 deletions clang/test/SemaCXX/type-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1768,8 +1768,8 @@ void is_layout_compatible(int n)
static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), "");
static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), "");
static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) == bool(__has_cpp_attribute(no_unique_address)), ""); // FIXME: this is CWG2759
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) == bool(__has_cpp_attribute(no_unique_address)), ""); // FIXME: this is CWG2759
static_assert(__is_layout_compatible(CStruct, CStructNoUniqueAddress) != bool(__has_cpp_attribute(no_unique_address)), "");
static_assert(__is_layout_compatible(CStructNoUniqueAddress, CStructNoUniqueAddress2) != bool(__has_cpp_attribute(no_unique_address)), "");
static_assert(__is_layout_compatible(CStruct, CStructAlignment), "");
static_assert(__is_layout_compatible(CStruct, CStructAlignedMembers), ""); // FIXME: alignment of members impact common initial sequence
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), "");
Expand All @@ -1782,10 +1782,10 @@ void is_layout_compatible(int n)
static_assert(!__is_layout_compatible(void(CStruct2::*)(int), void(CStruct2::*)(char)), "");
static_assert(__is_layout_compatible(CStructNested, CStructNested2), "");
static_assert(__is_layout_compatible(UnionLayout, UnionLayout), "");
static_assert(__is_layout_compatible(UnionLayout, UnionLayout2), "");
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout2), "");
static_assert(!__is_layout_compatible(UnionLayout, UnionLayout3), "");
static_assert(__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
static_assert(__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion2), "");
static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3), "");
static_assert(__is_layout_compatible(EnumLayout, EnumClassLayout), "");
static_assert(__is_layout_compatible(EnumForward, EnumForward), "");
static_assert(__is_layout_compatible(EnumForward, EnumClassForward), "");
Expand Down
2 changes: 1 addition & 1 deletion clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -16362,7 +16362,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/2759.html">2759</a></td>
<td>DR</td>
<td>[[no_unique_address] and common initial sequence</td>
<td class="unknown" align="center">Unknown</td>
<td class="unreleased" align="center">Clang 19</td>
</tr>
<tr id="2760">
<td><a href="https://cplusplus.github.io/CWG/issues/2760.html">2760</a></td>
Expand Down