https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/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. >From 027c842e24d2d03ac9e0d0a7ec90641822d03048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Tue, 15 Sep 2026 06:34:27 +0200 Subject: [PATCH] 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)); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
