[clang] d2fcb0c - [clang][bytecode] Handle multiple base paths in dynamic_cast (#213592)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 3 06:47:14 PDT 2026
Author: Timm Baeder
Date: 2026-08-03T15:47:10+02:00
New Revision: d2fcb0c9e11f8d8bedc45db0aeba9e0a53141fe5
URL: https://github.com/llvm/llvm-project/commit/d2fcb0c9e11f8d8bedc45db0aeba9e0a53141fe5
DIFF: https://github.com/llvm/llvm-project/commit/d2fcb0c9e11f8d8bedc45db0aeba9e0a53141fe5.diff
LOG: [clang][bytecode] Handle multiple base paths in dynamic_cast (#213592)
This can happen via virtual bases.
Fixes https://github.com/llvm/llvm-project/issues/213569
Added:
Modified:
clang/lib/AST/ByteCode/Interp.cpp
clang/test/AST/ByteCode/dynamic-cast.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 475d206356de8..5a5a12752dec5 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, there might be more than one "direct" base. They
+ // can have
diff erent access specifiers. They must all be private to be
+ // considered 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());
+}
More information about the cfe-commits
mailing list