[clang][Interp] Refine diagnostics for casts from void*

This is still not perfect, but an improvement in general.
This commit is contained in:
Timm Bäder
2024-06-11 06:14:17 +02:00
parent 35ddc17f36
commit 529b43c1fd
3 changed files with 33 additions and 9 deletions

View File

@@ -318,7 +318,8 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (DiscardResult)
return this->discard(SubExpr);
std::optional<PrimType> FromT = classify(SubExpr->getType());
QualType SubExprTy = SubExpr->getType();
std::optional<PrimType> FromT = classify(SubExprTy);
std::optional<PrimType> ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;
@@ -326,9 +327,14 @@ bool ByteCodeExprGen<Emitter>::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))

View File

@@ -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<Pointer>();
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;
}

View File

@@ -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];