Skip to content

[clang] Implement __is_virtual_base_of() intrinsic #100393

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 26, 2024

Conversation

Endilll
Copy link
Contributor

@Endilll Endilll commented Jul 24, 2024

This patch adds compiler support for P2985R0 "A type trait for detecting virtual base classes".
Like we recently did with __is_layout_compatible() and __is_pointer_interconvertible_base_of(), we support it only in C++ mode, and reject VLAs.

Resolves #98310.

@Endilll Endilll added clang:frontend Language frontend issues, e.g. anything involving "Sema" c++26 labels Jul 24, 2024
@Endilll Endilll requested review from cor3ntin and Sirraide July 24, 2024 14:43
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Jul 24, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 24, 2024

@llvm/pr-subscribers-clang

Author: Vlad Serebrennikov (Endilll)

Changes

This patch adds compiler support for P2985R0 "A type trait for detecting virtual base classes".
Like we recently did with __is_layout_compatible() and __is_pointer_interconvertible_base_of(), we support it only in C++ mode, and reject VLAs.

Resolves #98310.


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

5 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+3)
  • (modified) clang/include/clang/Basic/TokenKinds.def (+1)
  • (modified) clang/lib/Parse/ParseExpr.cpp (+1)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+27)
  • (modified) clang/test/SemaCXX/type-traits.cpp (+71-2)
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 {};
 

@Endilll Endilll changed the title [clang] Impement __is_virtual_base_of() intrinsic [clang] Implement __is_virtual_base_of() intrinsic Jul 24, 2024
Comment on lines +6043 to +6045
if (!BaseRecord->isStructureOrClassType() ||
!DerivedRecord->isStructureOrClassType())
return false;
Copy link
Member

Choose a reason for hiding this comment

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

Is this check necessary? If it’s not a union, it has to be a class type, right? Or am I missing something obvious?

Copy link
Contributor

Choose a reason for hiding this comment

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

It could be an enum (enums can't have an inheritance relationship) - but this check is enough, we don't need the union check above.
I think this is a mismatch between the standard - which treats union as classes, and clang - which treats everything as record.

Copy link
Member

Choose a reason for hiding this comment

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

It could be an enum

I thought a TagType was either a RecordType (struct/class/union) or an EnumType (enum). Can a RecordType really be an enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIRC ObjC interfaces are also RecordTypes, and I don't think we want to bother with them.

Copy link
Collaborator

Choose a reason for hiding this comment

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

ObjC types don't inherit from RecordType, so I don't think this check is needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

(and I don't think you can have a virtual objective c interface so there is nothing of ObjC to support here)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

isStructureOrClassType is defined as follows:

bool Type::isStructureOrClassType() const {
if (const auto *RT = getAs<RecordType>()) {
RecordDecl *RD = RT->getDecl();
return RD->isStruct() || RD->isClass() || RD->isInterface();
}
return false;
}

So (1) ObjC doesn't have to inherit from RecordType to get involved, and (2) the function has a misleading name.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, isInterface() is defined on TagDecl, so it seems that a RecordType can still not be an ObjcInterface from what I can tell. Looks like RD->isInterface() check in here is just pointless.

Copy link
Member

Choose a reason for hiding this comment

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

It’s also maybe worth noting that the line containing the check is from 2014, so things may have been different back then

Comment on lines 6051 to 6052
if (Self.Context.hasSameUnqualifiedType(LhsT, RhsT))
return false;
Copy link
Member

Choose a reason for hiding this comment

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

I’m assuming this is just short-circuiting? I’m aware that this case is mentioned in the paper (‘A class is never a virtual base class of itself’), but I don’t think it’s possible for a type to be its own base class—virtual or not—so I don’t think this is required for correctness. Is the check for virtual bases expensive?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but I don’t think it’s possible for a type to be its own base class—virtual or not—

Well, std::is_base_of_v<T, T> is ought to be true per http://eel.is/c++draft/meta.rel#lib:is_base_of, even though I don't see this in core language wording (which might be the reason this is specified in the library in the first place).

Is the check for virtual bases expensive?

I haven't measured, but why do more work when we can help it?

Copy link
Member

Choose a reason for hiding this comment

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

I see how it is, yeah, in that sense, it’s be easier to just keep it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this actually does more work instead of less; most code will not pass in the same type as both arguments, right? So that means this check won't catch anything useful most of the time, but the below check still will catch this case (I believe).

@cor3ntin
Copy link
Contributor

Can you update LanguageExtensions.rst?

@Endilll
Copy link
Contributor Author

Endilll commented Jul 24, 2024

Can you update LanguageExtensions.rst?

Done.

Comment on lines +6043 to +6045
if (!BaseRecord->isStructureOrClassType() ||
!DerivedRecord->isStructureOrClassType())
return false;
Copy link
Collaborator

Choose a reason for hiding this comment

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

ObjC types don't inherit from RecordType, so I don't think this check is needed.

Comment on lines 6035 to 6036
DiagnoseVLAInCXXTypeTrait(Self, Lhs, tok::kw___is_virtual_base_of);
DiagnoseVLAInCXXTypeTrait(Self, Rhs, tok::kw___is_virtual_base_of);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess I'm surprised by this -- why are VLAs special?

Copy link
Member

Choose a reason for hiding this comment

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

We’ve been generally disallowing VLA’s in type-traits recently; there was some discussion about this somewhere. Don’t remember where exactly, but I think #88646 is a good starting point.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't want to introduce even more VLA extensions in C++ mode (this builtin is exposed only in C++ mode). This began with #88473 (comment)

!DerivedRecord->isStructureOrClassType())
return false;

if (Self.RequireCompleteType(Rhs->getTypeLoc().getBeginLoc(), RhsT,
Copy link
Collaborator

Choose a reason for hiding this comment

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

What does it mean for there to be a complete derived class type but an incomplete base class type? Shouldn't this require a complete type in both cases to give reasonable diagnostic behavior?

Copy link
Member

Choose a reason for hiding this comment

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

The proposal only mentions that the second type has to be complete. My guess is that the reasoning behind this is that in e.g. __is_virtual_base_of(A, B), if B is complete but A isn’t, then A can’t be a base of B—since a complete class can’t have an incomplete base—and therefore, it can’t be a virtual base either.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I hadn't realized that is_base_of already has the same requirement, so I don't insist on a change here. But that said, this presumes users don't have typos they'd like to catch. e.g.,

struct Bee { };
struct Be;

struct Derived : virtual Bee {};

static_assert(!__is_virtual_base_of(Be, Derived)); // Oops, I can't spell very well!

I think it would be much kinder to tell the user that Be is incomplete than let them be surprised.

Copy link
Contributor

Choose a reason for hiding this comment

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

What does it mean for there to be a complete derived class type but an incomplete base class type? Shouldn't this require a complete type in both cases to give reasonable diagnostic behavior?

There is no incomplete base type. We are asking whether some type is a base, and if it isn't, we don't care that it is complete. Type traits don't mandate completeness if they don't need to.

Comment on lines 6051 to 6052
if (Self.Context.hasSameUnqualifiedType(LhsT, RhsT))
return false;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this actually does more work instead of less; most code will not pass in the same type as both arguments, right? So that means this check won't catch anything useful most of the time, but the below check still will catch this case (I believe).

@cor3ntin
Copy link
Contributor

Following discussion in #98310, we should rename __is_virtual_base_of -> __builtin_is_virtual_base_of

Copy link

github-actions bot commented Jul 25, 2024

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

Copy link
Contributor

@cor3ntin cor3ntin left a comment

Choose a reason for hiding this comment

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

LGTM

@Endilll
Copy link
Contributor Author

Endilll commented Jul 25, 2024

@PeterChou1 I see you had landed clang-doc patches recently. Can you help?
CI is repeatedly failing on the following clang-doc test:

�_bk;t=1721926993260�******************** TEST 'Clang Tools :: clang-doc/basic-project.test' FAILED ********************
�_bk;t=1721926993260�Exit Code: 1
�_bk;t=1721926993260�
�_bk;t=1721926993260�Command Output (stdout):
�_bk;t=1721926993260�--
�_bk;t=1721926993260�Emiting docs in html format.
�_bk;t=1721926993260�Mapping decls...
�_bk;t=1721926993260�Collecting infos...
�_bk;t=1721926993260�Reducing 5 infos...
�_bk;t=1721926993260�Generating docs...
�_bk;t=1721926993260�Generating assets for docs...
�_bk;t=1721926993260�
�_bk;t=1721926993260�--
�_bk;t=1721926993260�Command Output (stderr):
�_bk;t=1721926993260�--
�_bk;t=1721926993260�RUN: at line 1: rm -rf /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp && mkdir -p /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/build
�_bk;t=1721926993260�+ rm -rf /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp
�_bk;t=1721926993260�+ mkdir -p /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/build
�_bk;t=1721926993260�RUN: at line 2: sed 's|$test_dir|/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc|g' /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/Inputs/basic-project/database_template.json > /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/build/compile_commands.json
�_bk;t=1721926993260�+ sed 's|$test_dir|/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc|g' /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/Inputs/basic-project/database_template.json
�_bk;t=1721926993260�RUN: at line 3: clang-doc --format=html --output=/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs --executor=all-TUs /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/build/compile_commands.json
�_bk;t=1721926993260�+ clang-doc --format=html --output=/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs --executor=all-TUs /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/build/compile_commands.json
�_bk;t=1721926993260�[1/3] Processing file /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Calculator.cpp
�_bk;t=1721926993260�[2/3] Processing file /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Circle.cpp
�_bk;t=1721926993260�[3/3] Processing file /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/Inputs/basic-project/src/Rectangle.cpp
�_bk;t=1721926993260�RUN: at line 4: FileCheck /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/basic-project.test -input-file=/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/index_json.js -check-prefix=JSON-INDEX
�_bk;t=1721926993260�+ FileCheck /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/basic-project.test -input-file=/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/index_json.js -check-prefix=JSON-INDEX
�_bk;t=1721926993260�RUN: at line 5: FileCheck /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/basic-project.test -input-file=/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE
�_bk;t=1721926993260�+ FileCheck /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/basic-project.test -input-file=/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/GlobalNamespace/Shape.html -check-prefix=HTML-SHAPE
�_bk;t=1721926993260�/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/basic-project.test:64:16: error: HTML-SHAPE: expected string not found in input
�_bk;t=1721926993260�// HTML-SHAPE: <h3 id="{{([0-9A-F]{40})}}">area</h3>
�_bk;t=1721926993260�               ^
�_bk;t=1721926993260�/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/GlobalNamespace/Shape.html:32:53: note: scanning from here
�_bk;t=1721926993260� <p>Defined at line 13 of file ./include/Shape.h</p>
�_bk;t=1721926993260�                                                    ^
�_bk;t=1721926993260�/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/GlobalNamespace/Shape.html:47:41: note: possible intended match here
�_bk;t=1721926993260� <a href="#12896F9255F880ECD4A6482CCFA58B238FA2CC49">area</a>
�_bk;t=1721926993260�                                        ^
�_bk;t=1721926993260�
�_bk;t=1721926993260�Input file: /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/build/tools/clang/tools/extra/test/clang-doc/Output/basic-project.test.tmp/docs/GlobalNamespace/Shape.html
�_bk;t=1721926993260�Check file: /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-x8zhz-1/llvm-project/github-pull-requests/clang-tools-extra/test/clang-doc/basic-project.test
�_bk;t=1721926993260�
�_bk;t=1721926993260�-dump-input=help explains the following input dump.
�_bk;t=1721926993260�
�_bk;t=1721926993260�Input was:
�_bk;t=1721926993260�<<<<<<
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�           27:  <div> 
�_bk;t=1721926993260�           28:  <div></div> 
�_bk;t=1721926993260�           29:  </div> 
�_bk;t=1721926993260�           30:  <h3 id="9B656AD929057D302C30872492792CA767195B6A">~Shape</h3> 
�_bk;t=1721926993260�           31:  <p>public void ~Shape()</p> 
�_bk;t=1721926993260�           32:  <p>Defined at line 13 of file ./include/Shape.h</p> 
�_bk;t=1721926993260�check:64'0                                                         X error: no match found
�_bk;t=1721926993260�           33:  <div> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~
�_bk;t=1721926993260�           34:  <div></div> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~~~~~~
�_bk;t=1721926993260�           35:  </div> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~
�_bk;t=1721926993260�           36:  </div> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~
�_bk;t=1721926993260�           37:  </div> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�           42:  <a href="#Functions">Functions</a> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�_bk;t=1721926993260�           43:  </span> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~~
�_bk;t=1721926993260�           44:  <ul> 
�_bk;t=1721926993260�check:64'0     ~~~~~~
�_bk;t=1721926993260�           45:  <li> 
�_bk;t=1721926993260�check:64'0     ~~~~~~
�_bk;t=1721926993260�           46:  <span> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~
�_bk;t=1721926993260�           47:  <a href="#12896F9255F880ECD4A6482CCFA58B238FA2CC49">area</a> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�_bk;t=1721926993260�check:64'1                                             ?                      possible intended match
�_bk;t=1721926993260�           48:  </span> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~~
�_bk;t=1721926993260�           49:  </li> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~
�_bk;t=1721926993260�           50:  <li> 
�_bk;t=1721926993260�check:64'0     ~~~~~~
�_bk;t=1721926993260�           51:  <span> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~
�_bk;t=1721926993260�           52:  <a href="#3A9D3608883E4953D215E21C8246A8D32F0C91EE">perimeter</a> 
�_bk;t=1721926993260�check:64'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�            .
�_bk;t=1721926993260�>>>>>>
�_bk;t=1721926993260�
�_bk;t=1721926993260�--
�_bk;t=1721926993260�
�_bk;t=1721926993260�********************

@cor3ntin
Copy link
Contributor

The CI issues are unrelated so I'll merge this (someone should investigate why clang-doc tests are still failing though @PeterChou1. Thanks)

@Endilll Thanks for the patch :)

@cor3ntin cor3ntin merged commit 988fd95 into llvm:main Jul 26, 2024
6 of 8 checks passed
@Endilll Endilll deleted the is-virtual-base-of branch July 26, 2024 10:00
@ldionne
Copy link
Member

ldionne commented Aug 23, 2024

The libc++ part: #105847

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++26 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P2985R0 A type trait for detecting virtual base classes
6 participants