Author: Timm Baeder
Date: 2026-06-29T13:51:37+02:00
New Revision: e60b4b69dc72b1f7d9faa2e811ae161e9aef78e4

URL: 
https://github.com/llvm/llvm-project/commit/e60b4b69dc72b1f7d9faa2e811ae161e9aef78e4
DIFF: 
https://github.com/llvm/llvm-project/commit/e60b4b69dc72b1f7d9faa2e811ae161e9aef78e4.diff

LOG: [clang][bytecode] Fix an assertion failure in dynamic_cast handling 
(#206447)

If `Ptr` is already a root pointer, the `getBase()` call ran into an
assertion. Fix this by moving the check to the start of the loop.

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 0396482517046..42736d108aec1 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -2139,14 +2139,15 @@ bool DynamicCast(InterpState &S, CodePtr OpPC, const 
Type *DestTypePtr,
   std::optional<PtrView> Result;
   // First, check simple downcasts without ambiguities.
   for (PtrView Iter = Ptr.view();;) {
+    if (Iter.isRoot() || !Iter.isBaseClass())
+      break;
+
     if (typesMatch(TargetType, Iter.getType())) {
       Result = Iter;
       break;
     }
     // Moving DOWN the type hierarchy.
     Iter = Iter.getBase();
-    if (Iter.isRoot() || !Iter.isBaseClass())
-      break;
   }
 
   // Simply walking down the type hierarchy has produced a valid result, use

diff  --git a/clang/test/AST/ByteCode/dynamic-cast.cpp 
b/clang/test/AST/ByteCode/dynamic-cast.cpp
index a40b455cecabf..bfde7a2a4c0c2 100644
--- a/clang/test/AST/ByteCode/dynamic-cast.cpp
+++ b/clang/test/AST/ByteCode/dynamic-cast.cpp
@@ -295,6 +295,20 @@ namespace UnrelatedAndRootPtr{
   static_assert(f());
 }
 
+namespace UnrelatedAndRootReference {
+  struct A {
+    virtual void foo();
+  };
+  struct B1 : A {};
+
+  struct B2 : A {};
+  struct C : B2 {};
+
+  constexpr C c;
+  static_assert(&dynamic_cast<B2 &>((B1 &)c), ""); // both-error {{not an 
integral constant expression}} \
+                                                   // both-note {{cast that 
performs the conversions of a reinterpret_cast is not allowed in a constant 
expression}}
+}
+
 namespace Invalid {
   struct S { virtual void s(); };
   struct A : S {};


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

Reply via email to