Skip to content

Commit

Permalink
[clang] Implement CWG2759 "[[no_unique_address] and common initial …
Browse files Browse the repository at this point in the history
…sequence" (#82607)

This patch implements said defect report resolution by adding additional
check to common initial sequence evaluation. Consequently, this fixes
CWG2759.
  • Loading branch information
Endilll committed Feb 22, 2024
1 parent da1880c commit 5c24c31
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 15 deletions.
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 @@ -19036,6 +19036,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

0 comments on commit 5c24c31

Please sign in to comment.