[clang] [clang][bytecode] Apply pointer casts to opaque pointers (PR #223607)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 03:59:06 PDT 2026
Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/223607 at github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/223607
>From 027c842e24d2d03ac9e0d0a7ec90641822d03048 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 15 Sep 2026 06:34:27 +0200
Subject: [PATCH 1/2] bos
---
clang/lib/AST/ByteCode/Compiler.cpp | 3 +-
clang/lib/AST/ByteCode/Interp.cpp | 62 ++++++++++++++++++++++++++---
clang/lib/AST/ByteCode/Interp.h | 36 +----------------
clang/lib/AST/ByteCode/Opcodes.td | 2 +-
clang/test/AST/ByteCode/c.c | 12 ++++++
5 files changed, 73 insertions(+), 42 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 473494c694a98..8d3bf08a8b9d4 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -776,7 +776,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) {
return this->emitFnPtrCast(E);
}
if (FromT == PT_Ptr)
- return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), E);
+ return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(),
+ E->getType().getTypePtr(), E);
return true;
}
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index cc1c61c87da50..2497bccb8c282 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -50,6 +50,15 @@ using namespace clang::interp;
#define USE_TAILCALLS 1
#endif
+// FIXME: Code duplication with Pointer.cpp
+static bool validType(QualType T) {
+ if (const RecordDecl *RD = T->getAsRecordDecl())
+ return ASTContext::hasLayout(RD);
+ return !T->isDependentType() && !T->isUndeducedAutoType() &&
+ !T->isSpecificBuiltinType(BuiltinType::UnknownAny) &&
+ !T->isIncompleteType();
+}
+
PRESERVE_NONE static bool RetValue(InterpState &S) {
llvm::report_fatal_error("Interpreter cannot return values");
}
@@ -1989,6 +1998,53 @@ bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType,
return true;
}
+bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr,
+ const Type *TargetType) {
+ const auto &Ptr = S.Stk.peek<Pointer>();
+
+ if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
+ bool HasValidResult = !Ptr.isZero();
+
+ if (HasValidResult) {
+ if (S.getStdAllocatorCaller("allocate"))
+ return true;
+
+ if (S.getLangOpts().CPlusPlus26 &&
+ S.getASTContext().hasSimilarType(Ptr.getType(),
+ TargetType->getPointeeType()))
+ return true;
+
+ const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
+ S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
+ << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
+ << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
+ } else if (!S.getLangOpts().CPlusPlus26) {
+ const SourceInfo &E = S.Current->getSource(OpPC);
+ S.CCEDiag(E, diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
+ << S.Current->getRange(OpPC);
+ }
+ } else {
+ const SourceInfo &E = S.Current->getSource(OpPC);
+ S.CCEDiag(E, diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
+ << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
+ }
+
+ // Retain the casted type for opaque pointers.
+ if (Ptr.isOpaquePointer()) {
+ Pointer P = S.Stk.pop<Pointer>();
+ auto OP = P.asOpaquePointer();
+
+ if (!validType(TargetType->getPointeeType()))
+ return Invalid(S, OpPC);
+
+ S.Stk.push<Pointer>(OP.withFieldType(TargetType), P.getByteOffset());
+ }
+
+ return true;
+}
+
static void compileFunction(InterpState &S, const Function *Func) {
const FunctionDecl *Definition;
if (!Func->getDecl()->hasBody(Definition))
@@ -3425,12 +3481,6 @@ bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth,
return floatAPCast<true>(S, OpPC, F, BitWidth, FPOI);
}
-static bool validType(QualType T) {
- if (const RecordDecl *RD = T->getAsRecordDecl())
- return ASTContext::hasLayout(RD);
- return true;
-}
-
bool arrayElemPtrOpaque(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
APSInt &&Index, bool AllowReplace) {
const OpaquePointer &OP = Ptr.asOpaquePointer();
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 747311f42d757..acd3892f2e202 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3193,40 +3193,8 @@ static inline bool FnPtrCast(InterpState &S, CodePtr OpPC) {
return true;
}
-static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
- const auto &Ptr = S.Stk.peek<Pointer>();
-
- if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
- bool HasValidResult = !Ptr.isZero();
-
- if (HasValidResult) {
- if (S.getStdAllocatorCaller("allocate"))
- return true;
-
- const auto &E = cast<CastExpr>(S.Current->getExpr(OpPC));
- if (S.getLangOpts().CPlusPlus26 &&
- S.getASTContext().hasSimilarType(Ptr.getType(),
- E->getType()->getPointeeType()))
- return true;
-
- S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
- << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
- << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
- } else if (!S.getLangOpts().CPlusPlus26) {
- const SourceInfo &E = S.Current->getSource(OpPC);
- S.CCEDiag(E, diag::note_constexpr_invalid_cast)
- << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
- << S.Current->getRange(OpPC);
- }
- } else {
- const SourceInfo &E = S.Current->getSource(OpPC);
- S.CCEDiag(E, diag::note_constexpr_invalid_cast)
- << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
- << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
- }
-
- return true;
-}
+bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr,
+ const Type *TargetType);
//===----------------------------------------------------------------------===//
// Zero, Nullptr
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index 1831dc161f0a5..8761bfce64d3f 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -859,7 +859,7 @@ def ShiftFixedPoint : Opcode {
}
def PtrPtrCast : Opcode {
- let Args = [ArgBool];
+ let Args = [ArgBool, ArgTypePtr];
}
diff --git a/clang/test/AST/ByteCode/c.c b/clang/test/AST/ByteCode/c.c
index 5c1cebf2af998..7dd3f667559ed 100644
--- a/clang/test/AST/ByteCode/c.c
+++ b/clang/test/AST/ByteCode/c.c
@@ -474,3 +474,15 @@ void AddrLabelDiffSub(void) {
// all-error {{use of undeclared label 'baz'}} \
// pedantic-warning 2{{use of GNU address-of-label extension}}
}
+
+void *memset(void*, int, unsigned long);
+typedef struct Parse Parse;
+struct Parse {
+ int aTempReg;
+ int sLastToken;
+};
+
+Parse sqlite3Prepare_sParse;
+void sqlite3Prepare(void) {
+ memset( ((char *)&sqlite3Prepare_sParse) + sizeof(int), 0, sizeof(int));
+}
>From 7ce6c09adbba1cbe70318c13b2eb1cd05f6996d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 15 Sep 2026 09:37:31 +0200
Subject: [PATCH 2/2] One more test
---
.../test/AST/ByteCode/builtin-object-size-codegen.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/clang/test/AST/ByteCode/builtin-object-size-codegen.c b/clang/test/AST/ByteCode/builtin-object-size-codegen.c
index 445a95f5487b9..d1880e803c097 100644
--- a/clang/test/AST/ByteCode/builtin-object-size-codegen.c
+++ b/clang/test/AST/ByteCode/builtin-object-size-codegen.c
@@ -134,3 +134,15 @@ void f17(void) {
// CHECK: store i32 8
gi = __builtin_object_size(h0.s1, 0);
}
+
+struct Parse {
+ int a;
+ char b;
+ short c;
+};
+struct Parse _P;
+void f18(void) {
+ int gi;
+ // CHECK: store i32 3
+ gi = __builtin_object_size((char*)&_P + 5, 0);
+}
More information about the cfe-commits
mailing list