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