[clang] 3afa38c - [clang][bytecode] Reject invalid opaque pointer base conversions (#231366)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 14 02:05:38 PDT 2026
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}}
+}
More information about the cfe-commits
mailing list