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

Conversation

Endilll
Copy link
Contributor

@Endilll Endilll commented Feb 22, 2024

This patch implements said defect report resolution by adding additional check to common initial sequence evaluation. Consequently, this fixes CWG2759.

No special handling of [[msvc::no_unique_address]] is performed, so it should follow [[no_unique_address]] behavior.

…sequence"

This patch implements said defect report resolution by adding additional check to common initial sequence evaluation. Consequently, this fixes CWG2759.

No special handling of `[[msvc::no_unique_address]]` is performed, so it should follow `[[no_unique_address]]` behavior.
@Endilll Endilll added the c++11 label Feb 22, 2024
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Feb 22, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 22, 2024

@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)

Changes

This patch implements said defect report resolution by adding additional check to common initial sequence evaluation. Consequently, this fixes CWG2759.

No special handling of [[msvc::no_unique_address]] is performed, so it should follow [[no_unique_address]] behavior.


Full diff: https://github.com/llvm/llvm-project/pull/82607.diff

5 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+4-2)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+5)
  • (modified) clang/test/CXX/drs/dr27xx.cpp (+83)
  • (modified) clang/test/SemaCXX/type-traits.cpp (+5-5)
  • (modified) clang/www/cxx_dr_status.html (+1-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bac166e6c35627..a7c0f2fbbe7604 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
 ^^^^^^^^^^^^^^^^^^^^^
@@ -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
 ------------------
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e8bfb215a5b4c5..aba8852f6cfca4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19033,6 +19033,11 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
       return false;
   }
 
+  if (Field1->hasAttr<clang::NoUniqueAddressAttr>() ||
+      Field2->hasAttr<clang::NoUniqueAddressAttr>()) {
+    return false;
+  }
+
   return true;
 }
 
diff --git a/clang/test/CXX/drs/dr27xx.cpp b/clang/test/CXX/drs/dr27xx.cpp
index dd3fd5a20163fa..3fdf384bef27a7 100644
--- a/clang/test/CXX/drs/dr27xx.cpp
+++ b/clang/test/CXX/drs/dr27xx.cpp
@@ -10,6 +10,89 @@
 // 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>
diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp
index 2c35d5ee19a4c6..23c339ebdf0826 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -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), "");
@@ -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), "");
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 38e2cb63142662..8b638e06f4aab6 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -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>

@cor3ntin
Copy link
Contributor

No special handling of [[msvc::no_unique_address]] is performed, so it should follow [[no_unique_address]] behavior.

I do not think the code does that.
And we should test what it does.

At the very least, a type with msvc::no_unique_address should not be layout compatible with an equivalent declaration using no_unique_address.

Whether two msvc::no_unique_address are layout compatible is less important, because the intent of msvc::no_unique_address is not documented and/or msvc does not implement CWG2759

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Thanks!

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM modulo formatting nits

Co-authored-by: Timm Baeder <[email protected]>
Copy link

github-actions bot commented Feb 22, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@Endilll Endilll merged commit 5c24c31 into llvm:main Feb 22, 2024
@Endilll Endilll deleted the cwg2759 branch February 22, 2024 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++11 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants