llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) <details> <summary>Changes</summary> 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 index 5659594577111e..51592849e97edd 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -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), ""); +} + void is_signed() { //int t01[T(__is_signed(char))]; `````````` </details> 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