@@ -2628,7 +2628,29 @@ inline bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
2628
2628
}
2629
2629
}
2630
2630
2631
- return Call (S, OpPC, Func, VarArgSize);
2631
+ if (!Call (S, OpPC, Func, VarArgSize))
2632
+ return false ;
2633
+
2634
+ // Covariant return types. The return type of Overrider is a pointer
2635
+ // or reference to a class type.
2636
+ if (Overrider != InitialFunction &&
2637
+ Overrider->getReturnType ()->isPointerOrReferenceType () &&
2638
+ InitialFunction->getReturnType ()->isPointerOrReferenceType ()) {
2639
+ QualType OverriderPointeeType =
2640
+ Overrider->getReturnType ()->getPointeeType ();
2641
+ QualType InitialPointeeType =
2642
+ InitialFunction->getReturnType ()->getPointeeType ();
2643
+ // We've called Overrider above, but calling code expects us to return what
2644
+ // InitialFunction returned. According to the rules for covariant return
2645
+ // types, what InitialFunction returns needs to be a base class of what
2646
+ // Overrider returns. So, we need to do an upcast here.
2647
+ unsigned Offset = S.getContext ().collectBaseOffset (
2648
+ InitialPointeeType->getAsRecordDecl (),
2649
+ OverriderPointeeType->getAsRecordDecl ());
2650
+ return GetPtrBasePop (S, OpPC, Offset);
2651
+ }
2652
+
2653
+ return true ;
2632
2654
}
2633
2655
2634
2656
inline bool CallBI (InterpState &S, CodePtr &PC, const Function *Func,
0 commit comments