Author: Timm Baeder
Date: 2026-10-14T11:05:32+02:00
New Revision: 3afa38c6b8eac95660a4677b1353745c720212e5

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

LOG: [clang][bytecode] Reject invalid opaque pointer base conversions (#231366)

We can't reject them as they happen because that needs to work for other
tests. So reject them when computing the layout offset.

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Interp.h
    clang/lib/AST/ByteCode/Pointer.cpp
    clang/test/AST/ByteCode/invalid.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index ea115b6fef7e3..73f2d415cf56e 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1343,7 +1343,7 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr 
OpPC, CompareFn Fn) {
     std::optional<size_t> A = 
LHS.computeOffsetForComparison(S.getASTContext());
     std::optional<size_t> B = 
RHS.computeOffsetForComparison(S.getASTContext());
     if (!A || !B)
-      return Invalid(S, OpPC);
+      return false;
 
     S.Stk.push<BoolT>(BoolT::from(Fn(Compare(*A, *B))));
     return true;

diff  --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index 6ea2cae2a02ca..839a0929d1852 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -1415,19 +1415,21 @@ OpaquePointer::computeLayoutOffset(const ASTContext 
&ASTCtx) const {
   for (const PointerPathEntry &Entry : path()) {
     switch (Entry.Kind) {
     case PointerPathEntry::Base: {
-      const RecordDecl *RD = CurType->getAsRecordDecl();
+      const CXXRecordDecl *RD = CurType->getAsCXXRecordDecl();
       if (!ASTContext::hasLayout(RD))
         return std::nullopt;
 
+      const CXXRecordDecl *BaseDecl = Entry.RD.getPointer();
+      if (!RD->isDerivedFrom(BaseDecl))
+        return std::nullopt;
+
       const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
       if (Entry.RD.getInt())
-        Offset +=
-            Layout.getVBaseClassOffset(Entry.RD.getPointer()).getQuantity();
+        Offset += Layout.getVBaseClassOffset(BaseDecl).getQuantity();
       else
-        Offset +=
-            Layout.getBaseClassOffset(Entry.RD.getPointer()).getQuantity();
+        Offset += Layout.getBaseClassOffset(BaseDecl).getQuantity();
 
-      CurType = ASTCtx.getCanonicalTagType(Entry.RD.getPointer());
+      CurType = ASTCtx.getCanonicalTagType(BaseDecl);
     } break;
 
     case PointerPathEntry::Field: {

diff  --git a/clang/test/AST/ByteCode/invalid.cpp 
b/clang/test/AST/ByteCode/invalid.cpp
index a160c29169bc5..784fd95baf1dd 100644
--- a/clang/test/AST/ByteCode/invalid.cpp
+++ b/clang/test/AST/ByteCode/invalid.cpp
@@ -338,3 +338,12 @@ namespace PointerIntoInvalidRecord {
   } u;
   template int *foo<&u.baz>; // both-error {{non-type template argument is not 
a constant expression}}
 }
+
+namespace OpaquePtrPtrCast {
+  struct X {};
+  struct Y : X {};
+
+  constexpr struct Z {} z;
+  static_assert((X *)(Y *)&z != (X *)(Y *)&z, ""); // 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}}
+}


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

Reply via email to