https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/213592

This can happen via virtual bases.

Fixes https://github.com/llvm/llvm-project/issues/213569

>From cdca5701b716fef94eb1d214038fde09a5b22ede Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Mon, 3 Aug 2026 06:55:18 +0200
Subject: [PATCH] [clang][bytecode] Handle multiple base paths in dynamic_cast

This can happen via virtual bases.
---
 clang/lib/AST/ByteCode/Interp.cpp        |  8 ++++++--
 clang/test/AST/ByteCode/dynamic-cast.cpp | 14 ++++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 475d206356de8..2da4e4e764971 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2166,9 +2166,13 @@ bool DynamicCast(InterpState &S, CodePtr OpPC, const 
Type *DestTypePtr,
 
     CXXBasePaths Paths;
     getRecord(P.getBase())->isDerivedFrom(getRecord(P), Paths);
-    assert(std::distance(Paths.begin(), Paths.end()) == 1);
 
-    return Paths.front().Access == AS_private;
+    // Through virtual bases, they might be more than one "direct" base. They
+    // can have different access specifiers. They must all be private for the
+    // base to be private.
+    return llvm::all_of(Paths, [](const CXXBasePath &P) -> bool {
+      return P.Access == AS_private;
+    });
   };
 
   enum {
diff --git a/clang/test/AST/ByteCode/dynamic-cast.cpp 
b/clang/test/AST/ByteCode/dynamic-cast.cpp
index a81bab400a50a..83a745e271a28 100644
--- a/clang/test/AST/ByteCode/dynamic-cast.cpp
+++ b/clang/test/AST/ByteCode/dynamic-cast.cpp
@@ -338,3 +338,17 @@ namespace UnrelatedInitializingPtr {
   constexpr auto p = dynamic_cast<C &>(a); // both-error {{must be initialized 
by a constant expression}} \
                                            // both-note {{reference 
dynamic_cast failed: dynamic type 'UnrelatedInitializingPtr::D' of operand does 
not have a base class of type 'C'}}
 }
+
+namespace VirtualBase {
+  struct A { virtual constexpr ~A() = default; };
+  struct B : public virtual A {};
+  struct C : private virtual A {};
+  struct D : B, C {};
+
+  constexpr bool test() {
+    D d;
+    A *a = static_cast<B *>(&d);
+    return dynamic_cast<C *>(a) == static_cast<C *>(&d);
+  }
+  static_assert(test());
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to