[clang] Implement CWG1719 "Layout compatibility and cv-qualification revisited" (#82358)

This patch updates our internal notion of `layout-compatible` to ignore cv-qualification,
which in turn fixes `__is_layout_compatible` intrinsic.
This commit is contained in:
Vlad Serebrennikov
2024-02-21 19:02:20 +04:00
committed by GitHub
parent 5a023f564f
commit 73185854a3
5 changed files with 39 additions and 25 deletions

View File

@@ -98,9 +98,8 @@ C++20 Feature Support
- Implemented the `__is_layout_compatible` intrinsic to support
`P0466R5: Layout-compatibility and Pointer-interconvertibility Traits <https://wg21.link/P0466R5>`_.
Note: `CWG1719: Layout compatibility and cv-qualification revisited <https://cplusplus.github.io/CWG/issues/1719.html>`_
and `CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_
are not yet implemented.
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
^^^^^^^^^^^^^^^^^^^^^
@@ -120,6 +119,10 @@ Resolutions to C++ Defect Reports
in the template parameters, but is deduced from a previous argument.
(`#78449: <https://github.com/llvm/llvm-project/issues/78449>`_).
- Type qualifications are now ignored when evaluating layout compatibility
of two types.
(`CWG1719: Layout compatibility and cv-qualification revisited <https://cplusplus.github.io/CWG/issues/1719.html>`_).
C Language Changes
------------------

View File

@@ -19124,15 +19124,16 @@ static bool isLayoutCompatible(ASTContext &C, QualType T1, QualType T2) {
if (T1.isNull() || T2.isNull())
return false;
// C++11 [basic.types] p11:
// If two types T1 and T2 are the same type, then T1 and T2 are
// layout-compatible types.
if (C.hasSameType(T1, T2))
return true;
// C++20 [basic.types] p11:
// Two types cv1 T1 and cv2 T2 are layout-compatible types
// if T1 and T2 are the same type, layout-compatible enumerations (9.7.1),
// or layout-compatible standard-layout class types (11.4).
T1 = T1.getCanonicalType().getUnqualifiedType();
T2 = T2.getCanonicalType().getUnqualifiedType();
if (C.hasSameType(T1, T2))
return true;
const Type::TypeClass TC1 = T1->getTypeClass();
const Type::TypeClass TC2 = T2->getTypeClass();

View File

@@ -46,7 +46,7 @@ namespace dr1715 { // dr1715: 3.9
#endif
}
namespace dr1719 { // dr1719: no
namespace dr1719 { // dr1719: 19
#if __cplusplus >= 201103L
struct CStruct {
int one;
@@ -66,11 +66,11 @@ struct CStructWithQualifiers {
static_assert(__is_layout_compatible(CStruct, const CStruct2), "");
static_assert(__is_layout_compatible(CStruct, volatile CStruct2), "");
static_assert(__is_layout_compatible(const CStruct, volatile CStruct2), "");
// FIXME: all of the following pairs of types are layout-compatible
static_assert(!__is_layout_compatible(int, const int), "");
static_assert(!__is_layout_compatible(int, volatile int), "");
static_assert(!__is_layout_compatible(const int, volatile int), "");
static_assert(!__is_layout_compatible(CStruct, CStructWithQualifiers), "");
static_assert(__is_layout_compatible(int, const int), "");
static_assert(__is_layout_compatible(int, volatile int), "");
static_assert(__is_layout_compatible(const int, volatile int), "");
static_assert(__is_layout_compatible(CStruct, CStructWithQualifiers), "");
static_assert(__is_layout_compatible(int[], const volatile int[]), "");
#endif
} // namespace dr1719

View File

@@ -1609,7 +1609,12 @@ struct CStructNoUniqueAddress2 {
[[no_unique_address]] int two;
};
struct CStructAlignment {
struct alignas(64) CStructAlignment {
int one;
int two;
};
struct CStructAlignedMembers {
int one;
alignas(16) int two;
};
@@ -1711,13 +1716,17 @@ void is_layout_compatible(int n)
{
static_assert(__is_layout_compatible(void, void), "");
static_assert(!__is_layout_compatible(void, int), "");
static_assert(!__is_layout_compatible(void, const void), ""); // FIXME: this is CWG1719
static_assert(!__is_layout_compatible(void, volatile void), ""); // FIXME: this is CWG1719
static_assert(!__is_layout_compatible(const int, volatile int), ""); // FIXME: this is CWG1719
static_assert(__is_layout_compatible(void, const void), "");
static_assert(__is_layout_compatible(void, volatile void), "");
static_assert(__is_layout_compatible(const int, volatile int), "");
static_assert(__is_layout_compatible(int, int), "");
static_assert(!__is_layout_compatible(int, const int), ""); // FIXME: this is CWG1719
static_assert(!__is_layout_compatible(int, volatile int), ""); // FIXME: this is CWG1719
static_assert(!__is_layout_compatible(const int, volatile int), ""); // FIXME: this is CWG1719
static_assert(__is_layout_compatible(int, const int), "");
static_assert(__is_layout_compatible(int, volatile int), "");
static_assert(__is_layout_compatible(const int, volatile int), "");
static_assert(__is_layout_compatible(int *, int * __restrict), "");
// Note: atomic qualification matters for layout compatibility.
static_assert(!__is_layout_compatible(int, _Atomic int), "");
static_assert(__is_layout_compatible(_Atomic(int), _Atomic int), "");
static_assert(!__is_layout_compatible(int, unsigned int), "");
static_assert(!__is_layout_compatible(char, unsigned char), "");
static_assert(!__is_layout_compatible(char, signed char), "");
@@ -1758,10 +1767,11 @@ void is_layout_compatible(int n)
static_assert(!__is_layout_compatible(CppStructNonStandardByVirtBase, CppStructNonStandardByVirtBase2), "");
static_assert(!__is_layout_compatible(CppStructNonStandardBySameBase, CppStructNonStandardBySameBase2), "");
static_assert(!__is_layout_compatible(CppStructNonStandardBy2ndVirtBase, CppStructNonStandardBy2ndVirtBase2), "");
static_assert(!__is_layout_compatible(CStruct, CStructWithQualifiers), ""); // FIXME: this is CWG1719
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, CStructAlignment), "");
static_assert(__is_layout_compatible(CStruct, CStructAlignedMembers), ""); // FIXME: alignment of members impact common initial sequence
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds), "");
static_assert(__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds2), "");
static_assert(!__is_layout_compatible(CStructWithBitfelds, CStructWithBitfelds3), "");

View File

@@ -7812,7 +7812,7 @@ and <I>POD class</I></td>
<td><a href="https://cplusplus.github.io/CWG/issues/1334.html">1334</a></td>
<td>NAD</td>
<td>Layout compatibility and cv-qualification</td>
<td class="unknown" align="center">Unknown</td>
<td class="unreleased" align="center">Superseded by <a href="#1719">1719</a></td>
</tr>
<tr id="1335">
<td><a href="https://cplusplus.github.io/CWG/issues/1335.html">1335</a></td>
@@ -10122,7 +10122,7 @@ and <I>POD class</I></td>
<td><a href="https://cplusplus.github.io/CWG/issues/1719.html">1719</a></td>
<td>CD4</td>
<td>Layout compatibility and cv-qualification revisited</td>
<td class="unknown" align="center">Unknown</td>
<td class="unreleased" align="center">Clang 19</td>
</tr>
<tr id="1720">
<td><a href="https://cplusplus.github.io/CWG/issues/1720.html">1720</a></td>