[clang] [clang] Implement `__is_virtual_base_of()` intrinsic (PR #100393)

Vlad Serebrennikov via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 25 13:44:07 PDT 2024


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.vladislav at 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.vladislav at 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.vladislav at 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.vladislav at 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.vladislav at 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;
     }
 



More information about the cfe-commits mailing list