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()); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
