Skip to content

Commit 0bc8168

Browse files
authored
[clang][bytecode] Fix reinterpret_casts from pointer to non-pointers (#108811)
We need to be a little more careful here with whether or nor we are able to do the cast at all or not.
1 parent b9198a1 commit 0bc8168

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,18 +2638,46 @@ bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
26382638
const CXXReinterpretCastExpr *E) {
26392639
const Expr *SubExpr = E->getSubExpr();
26402640

2641-
bool Fatal = false;
26422641
std::optional<PrimType> FromT = classify(SubExpr);
26432642
std::optional<PrimType> ToT = classify(E);
2643+
26442644
if (!FromT || !ToT)
2645-
Fatal = true;
2646-
else
2647-
Fatal = (ToT != FromT);
2645+
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);
2646+
2647+
if (FromT == PT_Ptr || ToT == PT_Ptr) {
2648+
// Both types could be PT_Ptr because their expressions are glvalues.
2649+
std::optional<PrimType> PointeeFromT;
2650+
if (SubExpr->getType()->isPointerOrReferenceType())
2651+
PointeeFromT = classify(SubExpr->getType()->getPointeeType());
2652+
else
2653+
PointeeFromT = classify(SubExpr->getType());
2654+
2655+
std::optional<PrimType> PointeeToT;
2656+
if (E->getType()->isPointerOrReferenceType())
2657+
PointeeToT = classify(E->getType()->getPointeeType());
2658+
else
2659+
PointeeToT = classify(E->getType());
2660+
2661+
bool Fatal = true;
2662+
if (PointeeToT && PointeeFromT) {
2663+
if (isIntegralType(*PointeeFromT) && isIntegralType(*PointeeToT))
2664+
Fatal = false;
2665+
}
2666+
2667+
if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
2668+
return false;
2669+
2670+
if (E->getCastKind() == CK_LValueBitCast)
2671+
return this->delegate(SubExpr);
2672+
return this->VisitCastExpr(E);
2673+
}
26482674

2675+
// Try to actually do the cast.
2676+
bool Fatal = (ToT != FromT);
26492677
if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
26502678
return false;
26512679

2652-
return this->delegate(SubExpr);
2680+
return this->VisitCastExpr(E);
26532681
}
26542682

26552683
template <class Emitter>

clang/test/AST/ByteCode/invalid.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,7 @@ namespace Casts {
5454
B b;
5555
(void)*reinterpret_cast<void*>(&b); // both-error {{indirection not permitted on operand of type 'void *'}}
5656
}
57+
58+
/// Just make sure this doesn't crash.
59+
float PR9558 = reinterpret_cast<const float&>("asd");
5760
}

0 commit comments

Comments
 (0)