https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/100393
>From 772b5d85dff73de9f6a01a266bd201cbe04923ab Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Wed, 24 Jul 2024 17:38:50 +0300 Subject: [PATCH 1/5] [clang] Impement `__is_virtual_base_of()` intrinsic --- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/Basic/TokenKinds.def | 1 + clang/lib/Parse/ParseExpr.cpp | 1 + clang/lib/Sema/SemaExprCXX.cpp | 27 +++++++++ clang/test/SemaCXX/type-traits.cpp | 73 +++++++++++++++++++++++- 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ac1de0db9ce48..242f50bf23924 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -80,6 +80,9 @@ C++23 Feature Support C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Add ``__is_virtual_base_of`` intrinsic, which supports + `P2985R0 A type trait for detecting virtual base classes <https://wg21.link/p2985r0>`_ + Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 7f4912b9bcd96..1915e1f2588cb 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -529,6 +529,7 @@ TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX) TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX) TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) +TYPE_TRAIT_2(__is_virtual_base_of, IsVirtualBaseOf, KEYCXX) TYPE_TRAIT_1(__has_unique_object_representations, HasUniqueObjectRepresentations, KEYCXX) TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX) diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index a12c375c8d48c..582db2075616c 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -822,6 +822,7 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II, REVERTIBLE_TYPE_TRAIT(__is_unbounded_array); REVERTIBLE_TYPE_TRAIT(__is_union); REVERTIBLE_TYPE_TRAIT(__is_unsigned); + REVERTIBLE_TYPE_TRAIT(__is_virtual_base_of); REVERTIBLE_TYPE_TRAIT(__is_void); REVERTIBLE_TYPE_TRAIT(__is_volatile); REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 14d1f395af90e..6cba3a62b694d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6027,6 +6027,33 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI return cast<CXXRecordDecl>(rhsRecord->getDecl()) ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl())); } + case BTT_IsVirtualBaseOf: { + const RecordType *BaseRecord = LhsT->getAs<RecordType>(); + const RecordType *DerivedRecord = RhsT->getAs<RecordType>(); + + if (!BaseRecord || !DerivedRecord) { + DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_virtual_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_virtual_base_of); + return false; + } + + if (BaseRecord->isUnionType() || DerivedRecord->isUnionType()) + return false; + + if (!BaseRecord->isStructureOrClassType() || + !DerivedRecord->isStructureOrClassType()) + return false; + + if (Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT, + diag::err_incomplete_type)) + return false; + + if (Self.Context.hasSameUnqualifiedType(LhsT, RhsT)) + return false; + + return cast<CXXRecordDecl>(DerivedRecord->getDecl()) + ->isVirtuallyDerivedFrom(cast<CXXRecordDecl>(BaseRecord->getDecl())); + } case BTT_IsSame: return Self.Context.hasSameType(LhsT, RhsT); case BTT_TypeCompatible: { diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 23b07cac13eaf..4eedcebfaeffd 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -2402,11 +2402,11 @@ template<typename T> struct DerivedB : BaseA<T> { }; template<typename T> struct CrazyDerived : T { }; -class class_forward; // expected-note 2 {{forward declaration of 'class_forward'}} +class class_forward; // expected-note 4 {{forward declaration of 'class_forward'}} template <class T> class DerivedTemp : Base {}; template <class T> class NonderivedTemp {}; -template <class T> class UndefinedTemp; // expected-note {{declared here}} +template <class T> class UndefinedTemp; // expected-note 2 {{declared here}} void is_base_of() { static_assert(__is_base_of(Base, Derived)); @@ -2457,6 +2457,75 @@ void is_base_of() { static_assert(!__is_base_of(DerivedB<int>, BaseA<int>)); } +struct DerivedTransitiveViaNonVirtual : Derived3 {}; +struct DerivedTransitiveViaVirtual : virtual Derived3 {}; + +template <typename T> +struct CrazyDerivedVirtual : virtual T {}; + +struct DerivedPrivate : private virtual Base {}; +struct DerivedProtected : protected virtual Base {}; +struct DerivedPrivatePrivate : private DerivedPrivate {}; +struct DerivedPrivateProtected : private DerivedProtected {}; +struct DerivedProtectedPrivate : protected DerivedProtected {}; +struct DerivedProtectedProtected : protected DerivedProtected {}; + +void is_virtual_base_of(int n) { + static_assert(!__is_virtual_base_of(Base, Derived)); + static_assert(!__is_virtual_base_of(const Base, Derived)); + static_assert(!__is_virtual_base_of(Derived, Base)); + static_assert(!__is_virtual_base_of(Derived, int)); + static_assert(!__is_virtual_base_of(Base, Base)); + static_assert(!__is_virtual_base_of(Base, Derived3)); + static_assert(!__is_virtual_base_of(Derived, Derived3)); + static_assert(__is_virtual_base_of(Derived2b, Derived3)); + static_assert(__is_virtual_base_of(Derived2a, Derived3)); + static_assert(!__is_virtual_base_of(BaseA<int>, DerivedB<int>)); + static_assert(!__is_virtual_base_of(DerivedB<int>, BaseA<int>)); + static_assert(!__is_virtual_base_of(Union, Union)); + static_assert(!__is_virtual_base_of(Empty, Empty)); + static_assert(!__is_virtual_base_of(class_forward, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} + static_assert(!__is_virtual_base_of(Empty, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} + static_assert(!__is_virtual_base_of(Base&, Derived&)); + static_assert(!__is_virtual_base_of(Base[10], Derived[10])); + static_assert(!__is_virtual_base_of(Base[n], Derived[n])); // expected-error 2 {{variable length arrays are not supported in '__is_virtual_base_of'}} + static_assert(!__is_virtual_base_of(int, int)); + static_assert(!__is_virtual_base_of(int[], int[])); + static_assert(!__is_virtual_base_of(long, int)); + static_assert(!__is_virtual_base_of(Base, DerivedTemp<int>)); + static_assert(!__is_virtual_base_of(Base, NonderivedTemp<int>)); + static_assert(!__is_virtual_base_of(Base, UndefinedTemp<int>)); // expected-error {{implicit instantiation of undefined template 'UndefinedTemp<int>'}} + static_assert(__is_virtual_base_of(Base, DerivedPrivate)); + static_assert(__is_virtual_base_of(Base, DerivedProtected)); + static_assert(__is_virtual_base_of(Base, DerivedPrivatePrivate)); + static_assert(__is_virtual_base_of(Base, DerivedPrivateProtected)); + static_assert(__is_virtual_base_of(Base, DerivedProtectedPrivate)); + static_assert(__is_virtual_base_of(Base, DerivedProtectedProtected)); + static_assert(__is_virtual_base_of(Derived2a, DerivedTransitiveViaNonVirtual)); + static_assert(__is_virtual_base_of(Derived2b, DerivedTransitiveViaNonVirtual)); + static_assert(__is_virtual_base_of(Derived2a, DerivedTransitiveViaVirtual)); + static_assert(__is_virtual_base_of(Derived2b, DerivedTransitiveViaVirtual)); + static_assert(!__is_virtual_base_of(Base, CrazyDerived<Base>)); + static_assert(!__is_virtual_base_of(CrazyDerived<Base>, Base)); + static_assert(__is_virtual_base_of(Base, CrazyDerivedVirtual<Base>)); + static_assert(!__is_virtual_base_of(CrazyDerivedVirtual<Base>, Base)); + + static_assert(!__is_virtual_base_of(IncompleteUnion, IncompleteUnion)); + static_assert(!__is_virtual_base_of(Union, IncompleteUnion)); + static_assert(!__is_virtual_base_of(IncompleteUnion, Union)); + static_assert(!__is_virtual_base_of(IncompleteStruct, IncompleteUnion)); + static_assert(!__is_virtual_base_of(IncompleteUnion, IncompleteStruct)); + static_assert(!__is_virtual_base_of(Empty, IncompleteUnion)); + static_assert(!__is_virtual_base_of(IncompleteUnion, Empty)); + static_assert(!__is_virtual_base_of(int, IncompleteUnion)); + static_assert(!__is_virtual_base_of(IncompleteUnion, int)); + static_assert(!__is_virtual_base_of(Empty, Union)); + static_assert(!__is_virtual_base_of(Union, Empty)); + static_assert(!__is_virtual_base_of(int, Empty)); + static_assert(!__is_virtual_base_of(Union, int)); + static_assert(!__is_virtual_base_of(IncompleteStruct, IncompleteStruct[n])); // expected-error {{variable length arrays are not supported in '__is_virtual_base_of'}} +} + template<class T, class U> class TemplateClass {}; >From 8b0b0c5e38a7377a590e08c532c6343b5fbf5f2e Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Wed, 24 Jul 2024 21:44:51 +0300 Subject: [PATCH 2/5] Address reviewer feedback --- clang/docs/LanguageExtensions.rst | 1 + clang/lib/Parse/ParseExpr.cpp | 1 - clang/test/SemaCXX/type-traits.cpp | 1 + 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 81784c75081ba..dcb05a00f3280 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1660,6 +1660,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__is_unsigned`` (C++, Embarcadero): Returns false for enumeration types. Note, before Clang 13, returned true for enumeration types if the underlying type was unsigned. +* ``__is_virtual_base_of`` (C++, GNU, Microsoft) * ``__is_void`` (C++, Embarcadero) * ``__is_volatile`` (C++, Embarcadero) * ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 582db2075616c..a12c375c8d48c 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -822,7 +822,6 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II, REVERTIBLE_TYPE_TRAIT(__is_unbounded_array); REVERTIBLE_TYPE_TRAIT(__is_union); REVERTIBLE_TYPE_TRAIT(__is_unsigned); - REVERTIBLE_TYPE_TRAIT(__is_virtual_base_of); REVERTIBLE_TYPE_TRAIT(__is_void); REVERTIBLE_TYPE_TRAIT(__is_volatile); REVERTIBLE_TYPE_TRAIT(__reference_binds_to_temporary); diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 4eedcebfaeffd..60be35be2aae2 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -2486,6 +2486,7 @@ void is_virtual_base_of(int n) { static_assert(!__is_virtual_base_of(Empty, Empty)); static_assert(!__is_virtual_base_of(class_forward, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} static_assert(!__is_virtual_base_of(Empty, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} + static_assert(!__is_virtual_base_of(class_forward, Empty)); static_assert(!__is_virtual_base_of(Base&, Derived&)); static_assert(!__is_virtual_base_of(Base[10], Derived[10])); static_assert(!__is_virtual_base_of(Base[n], Derived[n])); // expected-error 2 {{variable length arrays are not supported in '__is_virtual_base_of'}} >From da449c9eb715c5cf2a6e77918b4dc0207360bb7d Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Thu, 25 Jul 2024 16:18:37 +0300 Subject: [PATCH 3/5] Remove short-circuiting --- clang/lib/Sema/SemaExprCXX.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 6cba3a62b694d..f5dc29b1a87fe 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6048,9 +6048,6 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI diag::err_incomplete_type)) return false; - if (Self.Context.hasSameUnqualifiedType(LhsT, RhsT)) - return false; - return cast<CXXRecordDecl>(DerivedRecord->getDecl()) ->isVirtuallyDerivedFrom(cast<CXXRecordDecl>(BaseRecord->getDecl())); } >From 89131195e8c5e5284b9ffe196492e853a56b6834 Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Thu, 25 Jul 2024 16:27:34 +0300 Subject: [PATCH 4/5] Rename to `__builtin_is_virtual_base_of` --- clang/docs/LanguageExtensions.rst | 2 +- clang/docs/ReleaseNotes.rst | 2 +- clang/include/clang/Basic/TokenKinds.def | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 4 +- clang/test/SemaCXX/type-traits.cpp | 108 +++++++++++------------ 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index dcb05a00f3280..a747464582e77 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1546,6 +1546,7 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__array_extent(type, dim)`` (Embarcadero): The ``dim``'th array bound in the type ``type``, or ``0`` if ``dim >= __array_rank(type)``. +* ``__builtin_is_virtual_base_of`` (C++, GNU, Microsoft) * ``__can_pass_in_regs`` (C++) Returns whether a class can be passed in registers under the current ABI. This type can only be applied to unqualified class types. @@ -1660,7 +1661,6 @@ The following type trait primitives are supported by Clang. Those traits marked * ``__is_unsigned`` (C++, Embarcadero): Returns false for enumeration types. Note, before Clang 13, returned true for enumeration types if the underlying type was unsigned. -* ``__is_virtual_base_of`` (C++, GNU, Microsoft) * ``__is_void`` (C++, Embarcadero) * ``__is_volatile`` (C++, Embarcadero) * ``__reference_binds_to_temporary(T, U)`` (Clang): Determines whether a diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 242f50bf23924..42108eddab560 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -80,7 +80,7 @@ C++23 Feature Support C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ -- Add ``__is_virtual_base_of`` intrinsic, which supports +- Add ``__builtin_is_virtual_base_of`` intrinsic, which supports `P2985R0 A type trait for detecting virtual base classes <https://wg21.link/p2985r0>`_ Resolutions to C++ Defect Reports diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 1915e1f2588cb..6e57f0c7367da 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -501,6 +501,7 @@ TYPE_TRAIT_1(__has_trivial_move_assign, HasTrivialMoveAssign, KEYCXX) TYPE_TRAIT_1(__has_trivial_move_constructor, HasTrivialMoveConstructor, KEYCXX) // GNU and MS Type Traits +TYPE_TRAIT_2(__builtin_is_virtual_base_of, IsVirtualBaseOf, KEYCXX) TYPE_TRAIT_1(__has_nothrow_assign, HasNothrowAssign, KEYCXX) TYPE_TRAIT_1(__has_nothrow_copy, HasNothrowCopy, KEYCXX) TYPE_TRAIT_1(__has_nothrow_constructor, HasNothrowConstructor, KEYCXX) @@ -529,7 +530,6 @@ TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX) TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX) TYPE_TRAIT_1(__is_union, IsUnion, KEYCXX) -TYPE_TRAIT_2(__is_virtual_base_of, IsVirtualBaseOf, KEYCXX) TYPE_TRAIT_1(__has_unique_object_representations, HasUniqueObjectRepresentations, KEYCXX) TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f5dc29b1a87fe..88a708bc7ab14 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6032,8 +6032,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI const RecordType *DerivedRecord = RhsT->getAs<RecordType>(); if (!BaseRecord || !DerivedRecord) { - DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_virtual_base_of); - DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_virtual_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___builtin_is_virtual_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___builtin_is_virtual_base_of); return false; } diff --git a/clang/test/SemaCXX/type-traits.cpp b/clang/test/SemaCXX/type-traits.cpp index 60be35be2aae2..e131212bb1071 100644 --- a/clang/test/SemaCXX/type-traits.cpp +++ b/clang/test/SemaCXX/type-traits.cpp @@ -2471,60 +2471,60 @@ struct DerivedProtectedPrivate : protected DerivedProtected {}; struct DerivedProtectedProtected : protected DerivedProtected {}; void is_virtual_base_of(int n) { - static_assert(!__is_virtual_base_of(Base, Derived)); - static_assert(!__is_virtual_base_of(const Base, Derived)); - static_assert(!__is_virtual_base_of(Derived, Base)); - static_assert(!__is_virtual_base_of(Derived, int)); - static_assert(!__is_virtual_base_of(Base, Base)); - static_assert(!__is_virtual_base_of(Base, Derived3)); - static_assert(!__is_virtual_base_of(Derived, Derived3)); - static_assert(__is_virtual_base_of(Derived2b, Derived3)); - static_assert(__is_virtual_base_of(Derived2a, Derived3)); - static_assert(!__is_virtual_base_of(BaseA<int>, DerivedB<int>)); - static_assert(!__is_virtual_base_of(DerivedB<int>, BaseA<int>)); - static_assert(!__is_virtual_base_of(Union, Union)); - static_assert(!__is_virtual_base_of(Empty, Empty)); - static_assert(!__is_virtual_base_of(class_forward, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} - static_assert(!__is_virtual_base_of(Empty, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} - static_assert(!__is_virtual_base_of(class_forward, Empty)); - static_assert(!__is_virtual_base_of(Base&, Derived&)); - static_assert(!__is_virtual_base_of(Base[10], Derived[10])); - static_assert(!__is_virtual_base_of(Base[n], Derived[n])); // expected-error 2 {{variable length arrays are not supported in '__is_virtual_base_of'}} - static_assert(!__is_virtual_base_of(int, int)); - static_assert(!__is_virtual_base_of(int[], int[])); - static_assert(!__is_virtual_base_of(long, int)); - static_assert(!__is_virtual_base_of(Base, DerivedTemp<int>)); - static_assert(!__is_virtual_base_of(Base, NonderivedTemp<int>)); - static_assert(!__is_virtual_base_of(Base, UndefinedTemp<int>)); // expected-error {{implicit instantiation of undefined template 'UndefinedTemp<int>'}} - static_assert(__is_virtual_base_of(Base, DerivedPrivate)); - static_assert(__is_virtual_base_of(Base, DerivedProtected)); - static_assert(__is_virtual_base_of(Base, DerivedPrivatePrivate)); - static_assert(__is_virtual_base_of(Base, DerivedPrivateProtected)); - static_assert(__is_virtual_base_of(Base, DerivedProtectedPrivate)); - static_assert(__is_virtual_base_of(Base, DerivedProtectedProtected)); - static_assert(__is_virtual_base_of(Derived2a, DerivedTransitiveViaNonVirtual)); - static_assert(__is_virtual_base_of(Derived2b, DerivedTransitiveViaNonVirtual)); - static_assert(__is_virtual_base_of(Derived2a, DerivedTransitiveViaVirtual)); - static_assert(__is_virtual_base_of(Derived2b, DerivedTransitiveViaVirtual)); - static_assert(!__is_virtual_base_of(Base, CrazyDerived<Base>)); - static_assert(!__is_virtual_base_of(CrazyDerived<Base>, Base)); - static_assert(__is_virtual_base_of(Base, CrazyDerivedVirtual<Base>)); - static_assert(!__is_virtual_base_of(CrazyDerivedVirtual<Base>, Base)); - - static_assert(!__is_virtual_base_of(IncompleteUnion, IncompleteUnion)); - static_assert(!__is_virtual_base_of(Union, IncompleteUnion)); - static_assert(!__is_virtual_base_of(IncompleteUnion, Union)); - static_assert(!__is_virtual_base_of(IncompleteStruct, IncompleteUnion)); - static_assert(!__is_virtual_base_of(IncompleteUnion, IncompleteStruct)); - static_assert(!__is_virtual_base_of(Empty, IncompleteUnion)); - static_assert(!__is_virtual_base_of(IncompleteUnion, Empty)); - static_assert(!__is_virtual_base_of(int, IncompleteUnion)); - static_assert(!__is_virtual_base_of(IncompleteUnion, int)); - static_assert(!__is_virtual_base_of(Empty, Union)); - static_assert(!__is_virtual_base_of(Union, Empty)); - static_assert(!__is_virtual_base_of(int, Empty)); - static_assert(!__is_virtual_base_of(Union, int)); - static_assert(!__is_virtual_base_of(IncompleteStruct, IncompleteStruct[n])); // expected-error {{variable length arrays are not supported in '__is_virtual_base_of'}} + static_assert(!__builtin_is_virtual_base_of(Base, Derived)); + static_assert(!__builtin_is_virtual_base_of(const Base, Derived)); + static_assert(!__builtin_is_virtual_base_of(Derived, Base)); + static_assert(!__builtin_is_virtual_base_of(Derived, int)); + static_assert(!__builtin_is_virtual_base_of(Base, Base)); + static_assert(!__builtin_is_virtual_base_of(Base, Derived3)); + static_assert(!__builtin_is_virtual_base_of(Derived, Derived3)); + static_assert(__builtin_is_virtual_base_of(Derived2b, Derived3)); + static_assert(__builtin_is_virtual_base_of(Derived2a, Derived3)); + static_assert(!__builtin_is_virtual_base_of(BaseA<int>, DerivedB<int>)); + static_assert(!__builtin_is_virtual_base_of(DerivedB<int>, BaseA<int>)); + static_assert(!__builtin_is_virtual_base_of(Union, Union)); + static_assert(!__builtin_is_virtual_base_of(Empty, Empty)); + static_assert(!__builtin_is_virtual_base_of(class_forward, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} + static_assert(!__builtin_is_virtual_base_of(Empty, class_forward)); // expected-error {{incomplete type 'class_forward' where a complete type is required}} + static_assert(!__builtin_is_virtual_base_of(class_forward, Empty)); + static_assert(!__builtin_is_virtual_base_of(Base&, Derived&)); + static_assert(!__builtin_is_virtual_base_of(Base[10], Derived[10])); + static_assert(!__builtin_is_virtual_base_of(Base[n], Derived[n])); // expected-error 2 {{variable length arrays are not supported in '__builtin_is_virtual_base_of'}} + static_assert(!__builtin_is_virtual_base_of(int, int)); + static_assert(!__builtin_is_virtual_base_of(int[], int[])); + static_assert(!__builtin_is_virtual_base_of(long, int)); + static_assert(!__builtin_is_virtual_base_of(Base, DerivedTemp<int>)); + static_assert(!__builtin_is_virtual_base_of(Base, NonderivedTemp<int>)); + static_assert(!__builtin_is_virtual_base_of(Base, UndefinedTemp<int>)); // expected-error {{implicit instantiation of undefined template 'UndefinedTemp<int>'}} + static_assert(__builtin_is_virtual_base_of(Base, DerivedPrivate)); + static_assert(__builtin_is_virtual_base_of(Base, DerivedProtected)); + static_assert(__builtin_is_virtual_base_of(Base, DerivedPrivatePrivate)); + static_assert(__builtin_is_virtual_base_of(Base, DerivedPrivateProtected)); + static_assert(__builtin_is_virtual_base_of(Base, DerivedProtectedPrivate)); + static_assert(__builtin_is_virtual_base_of(Base, DerivedProtectedProtected)); + static_assert(__builtin_is_virtual_base_of(Derived2a, DerivedTransitiveViaNonVirtual)); + static_assert(__builtin_is_virtual_base_of(Derived2b, DerivedTransitiveViaNonVirtual)); + static_assert(__builtin_is_virtual_base_of(Derived2a, DerivedTransitiveViaVirtual)); + static_assert(__builtin_is_virtual_base_of(Derived2b, DerivedTransitiveViaVirtual)); + static_assert(!__builtin_is_virtual_base_of(Base, CrazyDerived<Base>)); + static_assert(!__builtin_is_virtual_base_of(CrazyDerived<Base>, Base)); + static_assert(__builtin_is_virtual_base_of(Base, CrazyDerivedVirtual<Base>)); + static_assert(!__builtin_is_virtual_base_of(CrazyDerivedVirtual<Base>, Base)); + + static_assert(!__builtin_is_virtual_base_of(IncompleteUnion, IncompleteUnion)); + static_assert(!__builtin_is_virtual_base_of(Union, IncompleteUnion)); + static_assert(!__builtin_is_virtual_base_of(IncompleteUnion, Union)); + static_assert(!__builtin_is_virtual_base_of(IncompleteStruct, IncompleteUnion)); + static_assert(!__builtin_is_virtual_base_of(IncompleteUnion, IncompleteStruct)); + static_assert(!__builtin_is_virtual_base_of(Empty, IncompleteUnion)); + static_assert(!__builtin_is_virtual_base_of(IncompleteUnion, Empty)); + static_assert(!__builtin_is_virtual_base_of(int, IncompleteUnion)); + static_assert(!__builtin_is_virtual_base_of(IncompleteUnion, int)); + static_assert(!__builtin_is_virtual_base_of(Empty, Union)); + static_assert(!__builtin_is_virtual_base_of(Union, Empty)); + static_assert(!__builtin_is_virtual_base_of(int, Empty)); + static_assert(!__builtin_is_virtual_base_of(Union, int)); + static_assert(!__builtin_is_virtual_base_of(IncompleteStruct, IncompleteStruct[n])); // expected-error {{variable length arrays are not supported in '__builtin_is_virtual_base_of'}} } template<class T, class U> >From 46f02b2ddfe1787d79d7469a63739d0b71d8897a Mon Sep 17 00:00:00 2001 From: Vlad Serebrennikov <serebrennikov.vladis...@gmail.com> Date: Thu, 25 Jul 2024 17:04:57 +0300 Subject: [PATCH 5/5] Apply clang-format suggestions --- clang/lib/Sema/SemaExprCXX.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 88a708bc7ab14..9e2bbc4cdfb2e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6032,8 +6032,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, const TypeSourceI const RecordType *DerivedRecord = RhsT->getAs<RecordType>(); if (!BaseRecord || !DerivedRecord) { - DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___builtin_is_virtual_base_of); - DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___builtin_is_virtual_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Lhs, + tok::kw___builtin_is_virtual_base_of); + DiagnoseVLAInCXXTypeTrait(Self, Rhs, + tok::kw___builtin_is_virtual_base_of); return false; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits