@@ -3290,6 +3290,52 @@ inline bool SideEffect(InterpState &S, CodePtr OpPC) {
32903290 return S.noteSideEffect ();
32913291}
32923292
3293+ inline bool CheckBitCast (InterpState &S, CodePtr OpPC, const Type *TargetType,
3294+ bool SrcIsVoidPtr) {
3295+ const auto &Ptr = S.Stk .peek <Pointer>();
3296+ if (Ptr.isZero ())
3297+ return true ;
3298+ if (!Ptr.isBlockPointer ())
3299+ return true ;
3300+
3301+ if (TargetType->isIntegerType ())
3302+ return true ;
3303+
3304+ if (SrcIsVoidPtr && S.getLangOpts ().CPlusPlus ) {
3305+ bool HasValidResult = !Ptr.isZero ();
3306+
3307+ if (HasValidResult) {
3308+ if (S.getStdAllocatorCaller (" allocate" ))
3309+ return true ;
3310+
3311+ const auto &E = cast<CastExpr>(S.Current ->getExpr (OpPC));
3312+ if (S.getLangOpts ().CPlusPlus26 &&
3313+ S.getASTContext ().hasSimilarType (Ptr.getType (),
3314+ QualType (TargetType, 0 )))
3315+ return true ;
3316+
3317+ S.CCEDiag (E, diag::note_constexpr_invalid_void_star_cast)
3318+ << E->getSubExpr ()->getType () << S.getLangOpts ().CPlusPlus26
3319+ << Ptr.getType ().getCanonicalType () << E->getType ()->getPointeeType ();
3320+ } else if (!S.getLangOpts ().CPlusPlus26 ) {
3321+ const SourceInfo &E = S.Current ->getSource (OpPC);
3322+ S.CCEDiag (E, diag::note_constexpr_invalid_cast)
3323+ << diag::ConstexprInvalidCastKind::CastFrom << " 'void *'"
3324+ << S.Current ->getRange (OpPC);
3325+ }
3326+ }
3327+
3328+ QualType PtrType = Ptr.getType ();
3329+ if (PtrType->isRecordType () &&
3330+ PtrType->getAsRecordDecl () != TargetType->getAsRecordDecl ()) {
3331+ S.CCEDiag (S.Current ->getSource (OpPC), diag::note_constexpr_invalid_cast)
3332+ << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
3333+ << S.getLangOpts ().CPlusPlus << S.Current ->getRange (OpPC);
3334+ return false ;
3335+ }
3336+ return true ;
3337+ }
3338+
32933339// / Same here, but only for casts.
32943340inline bool InvalidCast (InterpState &S, CodePtr OpPC, CastKind Kind,
32953341 bool Fatal) {
0 commit comments