[clang] 1f83538 - [clang][bytecode] Apply pointer casts to opaque pointers (#223607)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 15 08:54:05 PDT 2026
Author: Timm Baeder
Date: 2026-09-15T17:53:59+02:00
New Revision: 1f83538aa13d9a622c36226e7c8a60ba58bb68f0
URL: https://github.com/llvm/llvm-project/commit/1f83538aa13d9a622c36226e7c8a60ba58bb68f0
DIFF: https://github.com/llvm/llvm-project/commit/1f83538aa13d9a622c36226e7c8a60ba58bb68f0.diff
LOG: [clang][bytecode] Apply pointer casts to opaque pointers (#223607)
For `((char *)&sqlite3Prepare_sParse) + 4`, the final byte offset should
be `4`, not `4 * sizeof(sqlite3Prepare_sParse)`. To handle that, we need
to actually pass the cast along to the opaque pointer.
Added:
Modified:
clang/lib/AST/ByteCode/Compiler.cpp
clang/lib/AST/ByteCode/Interp.cpp
clang/lib/AST/ByteCode/Interp.h
clang/lib/AST/ByteCode/Opcodes.td
clang/test/AST/ByteCode/builtin-object-size-codegen.c
clang/test/AST/ByteCode/c.c
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 64570635b7b3b..af1fd1c83c509 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 5b0f16abdbf46..47177ffdae0f6 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");
}
@@ -1935,6 +1944,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))
@@ -3370,12 +3426,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 aa187fab64a3a..fd1af9176496c 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3188,40 +3188,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 a3aaeff67e301..8a90962aeaea5 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -860,7 +860,7 @@ def ShiftFixedPoint : Opcode {
}
def PtrPtrCast : Opcode {
- let Args = [ArgBool];
+ let Args = [ArgBool, ArgTypePtr];
}
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);
+}
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));
+}
More information about the cfe-commits
mailing list