diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 74cae030bb9bb..c30262dd8a323 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -212,6 +212,10 @@ template bool Compiler::VisitCastExpr(const CastExpr *CE) { const Expr *SubExpr = CE->getSubExpr(); + if (isPunningDereference(SubExpr)) + return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, + CE); + if (DiscardResult) return this->delegate(SubExpr); @@ -5511,6 +5515,46 @@ bool Compiler::maybeEmitDeferredVarInit(const VarDecl *VD) { return true; } +template +bool Compiler::isPunningDereference(const Expr *E) +{ + E = E->IgnoreParenImpCasts(); + + const auto *UO = dyn_cast(E); + if (!UO || UO->getOpcode() != UO_Deref) + return false; + + const Expr *Base = UO->getSubExpr()->IgnoreParenImpCasts(); + const auto *Cast = dyn_cast(Base); + if (!Cast) + return false; + + // Only consider reinterpret-ish casts + switch (Cast->getCastKind()) { + case CK_BitCast: + case CK_PointerToIntegral: + case CK_IntegralToPointer: + case CK_AddressSpaceConversion: + break; + default: + return false; // CK_NoOp etc. are fine + } + + QualType DestPtrTy = Cast->getType(); + QualType SrcPtrTy = Cast->getSubExpr()->getType(); + if (!DestPtrTy->isPointerType() || !SrcPtrTy->isPointerType()) + return true; // super fishy, treat it as a pun + + QualType DestPointee = DestPtrTy->getPointeeType(); + QualType SrcPointee = SrcPtrTy->getPointeeType(); + + // If pointee types differ (ignoring qualifiers), its a pun + if (!Ctx.getASTContext().hasSameUnqualifiedType(DestPointee, SrcPointee)) + return true; + + return false; +} + static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) { assert(FD); assert(FD->getParent()->isUnion()); diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 5c46f75af4da3..2e814fe3e623b 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -423,6 +423,8 @@ class Compiler : public ConstStmtVisitor, bool>, bool checkLiteralType(const Expr *E); bool maybeEmitDeferredVarInit(const VarDecl *VD); + bool isPunningDereference(const Expr *E); + bool refersToUnion(const Expr *E); protected: