[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-12 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll created 
https://github.com/llvm/llvm-project/pull/81506

This patch implements `__is_layout_compatible`, which backs up 
`std::is_layout_compatible` type trait introduced in C++20 
([P0466R5](https://wg21.link/p0466r5) "Layout-compatibility and 
Pointer-interconvertibility Traits"). Name matched GCC and MSVC intrinsics.

Basically, this patch exposes our existing machinery for checking for layout 
compatibility and figuring out common initial sequences. Said machinery is a 
bit outdated, as it doesn't implement 
[CWG1719](https://cplusplus.github.io/CWG/issues/1719.html) "Layout 
compatibility and cv-qualification revisited" and 
[CWG2759](https://cplusplus.github.io/CWG/issues/2759.html) 
"`[[no_unique_address]` and common initial sequence". Those defect reports are 
considered out of scope of of this PR, but will be implemented in subsequent 
PRs.

Partially addresses #48204

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 1/2] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("n

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-12 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)


Changes

This patch implements `__is_layout_compatible`, which backs up 
`std::is_layout_compatible` type trait introduced in C++20 
([P0466R5](https://wg21.link/p0466r5) "Layout-compatibility and 
Pointer-interconvertibility Traits"). Name matched GCC and MSVC intrinsics.

Basically, this patch exposes our existing machinery for checking for layout 
compatibility and figuring out common initial sequences. Said machinery is a 
bit outdated, as it doesn't implement 
[CWG1719](https://cplusplus.github.io/CWG/issues/1719.html) "Layout 
compatibility and cv-qualification revisited" and 
[CWG2759](https://cplusplus.github.io/CWG/issues/2759.html) 
"`[[no_unique_address]` and common initial sequence". Those defect reports are 
considered out of scope of of this PR, but will be implemented in subsequent 
PRs.

Partially addresses #48204

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


7 Files Affected:

- (modified) clang/include/clang/Basic/TokenKinds.def (+1) 
- (modified) clang/include/clang/Sema/Sema.h (+2) 
- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+1) 
- (modified) clang/lib/Parse/ParseExpr.cpp (+1) 
- (modified) clang/lib/Sema/SemaChecking.cpp (+4) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+3) 
- (modified) clang/test/SemaCXX/type-traits.cpp (+83) 


``diff
diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
i

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-12 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff b45de48be24695b613f48ed21bb35f844454193b 
5599465e3c3921571fd22d18a5854ced3a752d80 -- clang/include/clang/Sema/Sema.h 
clang/lib/Parse/ParseDeclCXX.cpp clang/lib/Parse/ParseExpr.cpp 
clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaExprCXX.cpp 
clang/test/SemaCXX/type-traits.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ddeba32874..cd7d3c2ac1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14041,7 +14041,7 @@ private:
 
 public:
   bool SemaIsLayoutCompatible(QualType T1, QualType T2);
-  
+
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index c9360981c1..701d41a2e6 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1694,65 +1694,33 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   Tok.isOneOf(
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
 #include "clang/Basic/TransformTypeTraits.def"
-  tok::kw___is_abstract,
-  tok::kw___is_aggregate,
-  tok::kw___is_arithmetic,
-  tok::kw___is_array,
-  tok::kw___is_assignable,
-  tok::kw___is_base_of,
-  tok::kw___is_bounded_array,
-  tok::kw___is_class,
-  tok::kw___is_complete_type,
-  tok::kw___is_compound,
-  tok::kw___is_const,
-  tok::kw___is_constructible,
-  tok::kw___is_convertible,
-  tok::kw___is_convertible_to,
-  tok::kw___is_destructible,
-  tok::kw___is_empty,
-  tok::kw___is_enum,
-  tok::kw___is_floating_point,
-  tok::kw___is_final,
-  tok::kw___is_function,
-  tok::kw___is_fundamental,
-  tok::kw___is_integral,
-  tok::kw___is_interface_class,
-  tok::kw___is_layout_compatible,
-  tok::kw___is_literal,
-  tok::kw___is_lvalue_expr,
-  tok::kw___is_lvalue_reference,
+  tok::kw___is_abstract, tok::kw___is_aggregate,
+  tok::kw___is_arithmetic, tok::kw___is_array, tok::kw___is_assignable,
+  tok::kw___is_base_of, tok::kw___is_bounded_array, tok::kw___is_class,
+  tok::kw___is_complete_type, tok::kw___is_compound, 
tok::kw___is_const,
+  tok::kw___is_constructible, tok::kw___is_convertible,
+  tok::kw___is_convertible_to, tok::kw___is_destructible,
+  tok::kw___is_empty, tok::kw___is_enum, tok::kw___is_floating_point,
+  tok::kw___is_final, tok::kw___is_function, tok::kw___is_fundamental,
+  tok::kw___is_integral, tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible, tok::kw___is_literal,
+  tok::kw___is_lvalue_expr, tok::kw___is_lvalue_reference,
   tok::kw___is_member_function_pointer,
-  tok::kw___is_member_object_pointer,
-  tok::kw___is_member_pointer,
-  tok::kw___is_nothrow_assignable,
-  tok::kw___is_nothrow_constructible,
-  tok::kw___is_nothrow_convertible,
-  tok::kw___is_nothrow_destructible,
-  tok::kw___is_nullptr,
-  tok::kw___is_object,
-  tok::kw___is_pod,
-  tok::kw___is_pointer,
-  tok::kw___is_polymorphic,
-  tok::kw___is_reference,
-  tok::kw___is_referenceable,
-  tok::kw___is_rvalue_expr,
-  tok::kw___is_rvalue_reference,
-  tok::kw___is_same,
-  tok::kw___is_scalar,
-  tok::kw___is_scoped_enum,
-  tok::kw___is_sealed,
-  tok::kw___is_signed,
-  tok::kw___is_standard_layout,
-  tok::kw___is_trivial,
+  tok::kw___is_member_object_pointer, tok::kw___is_member_pointer,
+  tok::kw___is_nothrow_assignable, tok::kw___is_nothrow_constructible,
+  tok::kw___is_nothrow_convertible, tok::kw___is_nothrow_destructible,
+  tok::kw___is_nullptr, tok::kw___is_object, tok::kw___is_pod,
+  tok::kw___is_pointer, tok::kw___is_polymorphic,
+  tok::kw___is_reference, tok::kw___is_referenceable,
+  tok::kw___is_rvalue_expr, tok::kw___is_rvalue_reference,
+  tok::kw___is_same, tok::kw___is_scalar, tok::kw___is_scoped_enum,
+  tok::kw___is_sealed, tok::kw___is_signed,
+  tok::kw___is_standard_layout, tok::kw___is_trivial,
   tok::kw___is_trivially_equality_comparable,
   tok::kw___is_trivially_assignable,
-  tok::kw___is_trivially_constructible,
-  tok::kw___is_trivially_copyable,
-  tok::kw___is_unbounded_array,

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-12 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 1/3] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardB

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-12 Thread Vlad Serebrennikov via cfe-commits

Endilll wrote:

Formatting suggestions to `ParseDeclCXX.cpp` are too disruptive. I'm not going 
to commit them.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-12 Thread Timm Baeder via cfe-commits


@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);

tbaederr wrote:

Can this function no be `const`? And I guess the "Sema" prefix is to 
disambiguate with the existing `isLayoutCompatible`?

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread via cfe-commits

https://github.com/cor3ntin edited 
https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread via cfe-commits


@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,

cor3ntin wrote:

I don't think this is necessary. It exists for compatibility with old GCCs that 
would not have had the notion of layout compatibility 

(and I wonder if we could get rid of the whole switch ultimately @AaronBallman)

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread via cfe-commits

https://github.com/cor3ntin commented:

This looks good generally.
Can you add a changelog entry?
Can you add some doc in LanguageExtension.rst?

Thanks

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread via cfe-commits


@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);

cor3ntin wrote:

Agreed, this should be renamed IsLayoutCompatible (and be const)

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 1/5] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardB

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread Vlad Serebrennikov via cfe-commits


@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);

Endilll wrote:

Done

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 1/6] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardB

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-13 Thread Vlad Serebrennikov via cfe-commits


@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,

Endilll wrote:

Done

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-14 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman commented:

Thank you for this! Please be sure to also add a release note and documentation 
(https://clang.llvm.org/docs/LanguageExtensions.html#type-trait-primitives).

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-14 Thread Aaron Ballman via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

AaronBallman wrote:

Some additional test cases to consider:

* A type is layout compatible with its qualified version. e.g., `SomeStruct` 
and `const SomeStruct`
* Layout compatibility of function types (not function pointer types), e.g., 
`void(int)` and `void(int)`
* Diagnostics when given an incomplete type for either operand
* That `int` and `unsigned int` are not layout compatible
* That `char` and `signed char`/`unsigned char` are not layout compatible
* That an enumeration type and its underlying type are not layout compatible

If this catches bugs in the implementation of `isLayoutCompatible()`, that' 
fine, we can document the current behavior in the test with a FIXME and come 
back to addressing the issues in a follow-up.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-14 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman edited 
https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-15 Thread via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

cor3ntin wrote:

> * A type is layout compatible with its qualified version. e.g., `SomeStruct` 
> and `const SomeStruct`

We do not yet implement https://cplusplus.github.io/CWG/issues/1719.html, so 
some tests are better deferred to the implementation of that DR

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-15 Thread Aaron Ballman via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

AaronBallman wrote:

I think we should add those tests somewhere (either here or in dr1xxx.cpp) so 
1) we know we don't crash on them, 2) we're alerted to behavioral changes in 
this area, and 3) better documentation of existing behavior.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-16 Thread Vlad Serebrennikov via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

Endilll wrote:

> A type is layout compatible with its qualified version. e.g., SomeStruct and 
> const SomeStruct

Done. It even works correctly for class types.

> Layout compatibility of function types (not function pointer types), e.g., 
> void(int) and void(int)

Done. I added tests for function types, reference to functions, pointers to 
function, pointers to data members, pointers to member functions.

> Diagnostics when given an incomplete type for either operand

We don't issue any, as far as I can see. And I don't think we can when the 
types are the same, ignoring cv qualifiers:
> Two types cv1 T1 and cv2 T2 are [layout-compatible 
> types](http://eel.is/c++draft/basic.types.general#def:type,layout-compatible) 
> if T1 and T2 are the same type, [layout-compatible 
> enumerations](http://eel.is/c++draft/dcl.enum#def:layout-compatible,enumeration),
>  or [layout-compatible standard-layout class 
> types](http://eel.is/c++draft/class.mem#def:layout-compatible,class)[.](http://eel.is/c++draft/basic.types.general#11.sentence-1)

> That int and unsigned int are not layout compatible
> That char and signed char/unsigned char are not layout compatible
> That an enumeration type and its underlying type are not layout compatible

Done.

> I think we should add those tests somewhere (either here or in dr1xxx.cpp) so 
> 1) we know we don't crash on them, 2) we're alerted to behavioral changes in 
> this area, and 3) better documentation of existing behavior.

Agreed. I marked 1334 as superseded as 1719, and added a test for 1719.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
h

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-16 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll edited 
https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-16 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 1/8] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardB

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-16 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll edited 
https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-16 Thread Aaron Ballman via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

AaronBallman wrote:

> We don't issue any, as far as I can see. And I don't think we can when the 
> types are the same, ignoring cv qualifiers:

That's a bug, see 
https://eel.is/c++draft/tab:meta.rel#row-6-column-3-sentence-1: "T and U shall 
be complete types, cv void, or arrays of unknown bound."

but also: https://eel.is/c++draft/tab:meta.rel#row-6-column-3-sentence-1and 
http://eel.is/c++draft/class.mem#general-23 -- you can't test for layout 
compatibility if the class type is not complete because you don't know the 
members. So we should accept `void` but not `struct NeverDefined`.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-16 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 1/9] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardB

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-17 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 01/10] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandar

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-17 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 01/11] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandar

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-18 Thread via cfe-commits

https://github.com/cor3ntin edited 
https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-18 Thread via cfe-commits


@@ -90,6 +90,12 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Implemented `__is_layout_compatible` intrinsic, which backs up
+  `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits 
`_.
+  `CWG1719: Layout compatibility and cv-qualification revisited  
`_
+  and `CWG2759: [[no_unique_address] and common initial sequence 
`_
+  are not yet implemented.
+

cor3ntin wrote:

```suggestion
- Implemented the `__is_layout_compatible` intrinsic to support
  `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits 
`_.
  Note: `CWG1719: Layout compatibility and cv-qualification revisited  
`_
  and `CWG2759: [[no_unique_address] and common initial sequence 
`_
  are not yet implemented.

```

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-18 Thread via cfe-commits

https://github.com/cor3ntin approved this pull request.

LGTM!

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 01/12] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandar

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread A. Jiang via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

frederick-vs-ja wrote:

> * That an enumeration type and its underlying type are not layout compatible

This is possibly a defect 
(https://github.com/cplusplus/CWG/issues/39#issuecomment-1184791364, 
https://github.com/cplusplus/CWG/issues/95#issuecomment-1185260854), but no CWG 
issue is filed yet.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 01/13] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandar

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread Vlad Serebrennikov via cfe-commits


@@ -1558,6 +1558,89 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandardByProt2 : CStruct2 {
+  int five;
+protected:
+  int six;
+};
+struct CppStructNonStandardByVirtBase2 : virtual CStruct2 {
+};
+struct CppStructNonStandardBySameBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+struct CppStructNonStandardBy2ndVirtBase2 : CEmptyStruct2 {
+  CEmptyStruct member;
+};
+
+struct CStructWithQualifiers {
+  const int one;
+  volatile int two;
+};
+
+struct CStructNoUniqueAddress {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructNoUniqueAddress2 {
+  int one;
+  [[no_unique_address]] int two;
+};
+
+struct CStructAlignment {
+  int one;
+  alignas(16) int two;
+};
+
+struct CStructIncomplete;
+
+void is_layout_compatible()
+{
+  static_assert(__is_layout_compatible(void, void), "");
+  static_assert(__is_layout_compatible(int, int), "");
+  static_assert(__is_layout_compatible(int[], int[]), "");
+  static_assert(__is_layout_compatible(int[2], int[2]), "");
+  static_assert(__is_layout_compatible(CStruct, CStruct2), "");
+  static_assert(__is_layout_compatible(CEmptyStruct, CEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppEmptyStruct, CppEmptyStruct2), "");
+  static_assert(__is_layout_compatible(CppStructStandard, CppStructStandard2), 
"");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByBase, 
CppStructNonStandardByBase2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByVirt, 
CppStructNonStandardByVirt2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByMemb, 
CppStructNonStandardByMemb2), "");
+  static_assert(!__is_layout_compatible(CppStructNonStandardByProt, 
CppStructNonStandardByProt2), "");
+  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, 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(CStructIncomplete, CStructIncomplete), 
"");
+  static_assert(!__is_layout_compatible(CStruct, CStructIncomplete), "");
+}

Endilll wrote:

Thank you for mentioning that! I left a comment around enum tests.

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 01/14] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandar

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread Vlad Serebrennikov via cfe-commits


@@ -90,6 +90,12 @@ C++20 Feature Support
   behavior can use the flag '-Xclang -fno-skip-odr-check-in-gmf'.
   (`#79240 `_).
 
+- Implemented `__is_layout_compatible` intrinsic, which backs up
+  `P0466R5: Layout-compatibility and Pointer-interconvertibility Traits 
`_.
+  `CWG1719: Layout compatibility and cv-qualification revisited  
`_
+  and `CWG2759: [[no_unique_address] and common initial sequence 
`_
+  are not yet implemented.
+

Endilll wrote:

Done

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-19 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll updated 
https://github.com/llvm/llvm-project/pull/81506

>From 52b239153b2fc4f52e889ad2044daa6ed5cbc836 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov 
Date: Mon, 12 Feb 2024 17:44:38 +0300
Subject: [PATCH 01/15] Initial implementation

---
 clang/include/clang/Basic/TokenKinds.def |  1 +
 clang/include/clang/Sema/Sema.h  |  2 +
 clang/lib/Parse/ParseDeclCXX.cpp |  1 +
 clang/lib/Parse/ParseExpr.cpp|  1 +
 clang/lib/Sema/SemaChecking.cpp  |  4 ++
 clang/lib/Sema/SemaExprCXX.cpp   |  3 +
 clang/test/SemaCXX/type-traits.cpp   | 77 
 7 files changed, 89 insertions(+)

diff --git a/clang/include/clang/Basic/TokenKinds.def 
b/clang/include/clang/Basic/TokenKinds.def
index 23817cde7a9354..112bfe8b23c2c0 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -520,6 +520,7 @@ TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, 
KEYCXX)
 TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX)
 TYPE_TRAIT_1(__has_unique_object_representations,
  HasUniqueObjectRepresentations, KEYCXX)
+TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
 
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
 #include "clang/Basic/TransformTypeTraits.def"
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 851560f759f0e4..ddeba328749653 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14040,6 +14040,8 @@ class Sema final {
   bool SemaValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum);
 
 public:
+  bool SemaIsLayoutCompatible(QualType T1, QualType T2);
+  
   // Used by C++ template instantiation.
   ExprResult SemaBuiltinShuffleVector(CallExpr *TheCall);
   ExprResult SemaConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 79928ddb5af599..c9360981c1c1e4 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1717,6 +1717,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind 
TagTokKind,
   tok::kw___is_fundamental,
   tok::kw___is_integral,
   tok::kw___is_interface_class,
+  tok::kw___is_layout_compatible,
   tok::kw___is_literal,
   tok::kw___is_lvalue_expr,
   tok::kw___is_lvalue_reference,
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 52cebdb6f64bac..db21a7f1e9e368 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1114,6 +1114,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind 
ParseKind,
   REVERTIBLE_TYPE_TRAIT(__is_fundamental);
   REVERTIBLE_TYPE_TRAIT(__is_integral);
   REVERTIBLE_TYPE_TRAIT(__is_interface_class);
+  REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
   REVERTIBLE_TYPE_TRAIT(__is_literal);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
   REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 71e6e7230fc455..8aa744873f3704 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -19150,6 +19150,10 @@ static bool isLayoutCompatible(ASTContext &C, QualType 
T1, QualType T2) {
   return false;
 }
 
+bool Sema::SemaIsLayoutCompatible(QualType T1, QualType T2) {
+  return isLayoutCompatible(getASTContext(), T1, T2);
+}
+
 //===--- CHECK: pointer_with_type_tag attribute: datatypes should match //
 
 /// Given a type tag expression find the type tag itself.
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 246d2313e089f3..b279c367342fce 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5922,6 +5922,9 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait 
BTT, QualType LhsT,
 
 llvm_unreachable("unhandled type trait");
 return false;
+  }
+  case BTT_IsLayoutCompatible: {
+return Self.SemaIsLayoutCompatible(LhsT, RhsT);
   }
 default: llvm_unreachable("not a BTT");
   }
diff --git a/clang/test/SemaCXX/type-traits.cpp 
b/clang/test/SemaCXX/type-traits.cpp
index 5659594577111e..f50bedc275359b 100644
--- a/clang/test/SemaCXX/type-traits.cpp
+++ b/clang/test/SemaCXX/type-traits.cpp
@@ -1558,6 +1558,83 @@ void is_standard_layout()
   int t71[F(__is_standard_layout(HasEmptyIndirectBaseAsSecondUnionMember))];
 }
 
+struct CStruct2 {
+  int one;
+  int two;
+};
+
+struct CEmptyStruct2 {};
+
+struct CppEmptyStruct2 : CStruct2 {};
+struct CppStructStandard2 : CEmptyStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByBase2 : CStruct2 {
+  int three;
+  int four;
+};
+struct CppStructNonStandardByVirt2 : CStruct2 {
+  virtual void method() {}
+};
+struct CppStructNonStandardByMemb2 : CStruct2 {
+  CppStructNonStandardByVirt member;
+};
+struct CppStructNonStandar

[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-20 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman approved this pull request.

LGTM!

https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Implement `__is_layout_compatible` (PR #81506)

2024-02-20 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll closed 
https://github.com/llvm/llvm-project/pull/81506
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits