From 529b43c1fd435e1544bbd581fcf7191c3edfa20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 11 Jun 2024 06:14:17 +0200 Subject: [PATCH] [clang][Interp] Refine diagnostics for casts from void* This is still not perfect, but an improvement in general. --- clang/lib/AST/Interp/ByteCodeExprGen.cpp | 14 ++++++++++---- clang/lib/AST/Interp/Interp.h | 23 +++++++++++++++++++---- clang/lib/AST/Interp/Opcodes.td | 5 ++++- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 6654a27c9216..0899a98b3b95 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -318,7 +318,8 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { if (DiscardResult) return this->discard(SubExpr); - std::optional FromT = classify(SubExpr->getType()); + QualType SubExprTy = SubExpr->getType(); + std::optional FromT = classify(SubExprTy); std::optional ToT = classify(CE->getType()); if (!FromT || !ToT) return false; @@ -326,9 +327,14 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr *CE) { assert(isPtrType(*FromT)); assert(isPtrType(*ToT)); if (FromT == ToT) { - if (SubExpr->getType()->isVoidPointerType()) - return this->visit(SubExpr) && this->emitVoidPtrCast(CE); - return this->delegate(SubExpr); + if (CE->getType()->isVoidPointerType()) + return this->delegate(SubExpr); + + if (!this->visit(SubExpr)) + return false; + if (FromT == PT_Ptr) + return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE); + return true; } if (!this->visit(SubExpr)) diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 0ad710c5ec1a..784e138e1467 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1980,10 +1980,25 @@ static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, return true; } -static inline bool VoidPtrCast(InterpState &S, CodePtr OpPC) { - const SourceInfo &E = S.Current->getSource(OpPC); - S.CCEDiag(E, diag::note_constexpr_invalid_cast) - << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); +static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) { + const auto &Ptr = S.Stk.peek(); + + if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) { + bool HasValidResult = !Ptr.isZero(); + + if (HasValidResult) { + // FIXME: note_constexpr_invalid_void_star_cast + } else if (!S.getLangOpts().CPlusPlus26) { + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << 3 << "'void *'" << S.Current->getRange(OpPC); + } + } else { + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + } + return true; } diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index ac5426c87c21..45fc11e56457 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -665,7 +665,10 @@ def CastPointerIntegralAPS : Opcode { let HasGroup = 0; let Args = [ArgUint32]; } -def VoidPtrCast : Opcode; +def PtrPtrCast : Opcode { + let Args = [ArgBool]; + +} def DecayPtr : Opcode { let Types = [PtrTypeClass, PtrTypeClass];