@@ -1568,6 +1568,22 @@ inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
1568
1568
return true ;
1569
1569
}
1570
1570
1571
+ // / Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need
1572
+ // / to know what bitwidth the result should be.
1573
+ template <PrimType Name, class T = typename PrimConv<Name>::T>
1574
+ bool CastAP (InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1575
+ S.Stk .push <IntegralAP<false >>(
1576
+ IntegralAP<false >::from (S.Stk .pop <T>(), BitWidth));
1577
+ return true ;
1578
+ }
1579
+
1580
+ template <PrimType Name, class T = typename PrimConv<Name>::T>
1581
+ bool CastAPS (InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
1582
+ S.Stk .push <IntegralAP<true >>(
1583
+ IntegralAP<true >::from (S.Stk .pop <T>(), BitWidth));
1584
+ return true ;
1585
+ }
1586
+
1571
1587
template <PrimType Name, class T = typename PrimConv<Name>::T>
1572
1588
bool CastIntegralFloating (InterpState &S, CodePtr OpPC,
1573
1589
const llvm::fltSemantics *Sem,
@@ -1608,6 +1624,46 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
1608
1624
}
1609
1625
}
1610
1626
1627
+ static inline bool CastFloatingIntegralAP (InterpState &S, CodePtr OpPC,
1628
+ uint32_t BitWidth) {
1629
+ const Floating &F = S.Stk .pop <Floating>();
1630
+
1631
+ APSInt Result (BitWidth, /* IsUnsigned=*/ true );
1632
+ auto Status = F.convertToInteger (Result);
1633
+
1634
+ // Float-to-Integral overflow check.
1635
+ if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite ()) {
1636
+ const Expr *E = S.Current ->getExpr (OpPC);
1637
+ QualType Type = E->getType ();
1638
+
1639
+ S.CCEDiag (E, diag::note_constexpr_overflow) << F.getAPFloat () << Type;
1640
+ return S.noteUndefinedBehavior ();
1641
+ }
1642
+
1643
+ S.Stk .push <IntegralAP<true >>(IntegralAP<true >(Result));
1644
+ return CheckFloatResult (S, OpPC, F, Status);
1645
+ }
1646
+
1647
+ static inline bool CastFloatingIntegralAPS (InterpState &S, CodePtr OpPC,
1648
+ uint32_t BitWidth) {
1649
+ const Floating &F = S.Stk .pop <Floating>();
1650
+
1651
+ APSInt Result (BitWidth, /* IsUnsigned=*/ false );
1652
+ auto Status = F.convertToInteger (Result);
1653
+
1654
+ // Float-to-Integral overflow check.
1655
+ if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite ()) {
1656
+ const Expr *E = S.Current ->getExpr (OpPC);
1657
+ QualType Type = E->getType ();
1658
+
1659
+ S.CCEDiag (E, diag::note_constexpr_overflow) << F.getAPFloat () << Type;
1660
+ return S.noteUndefinedBehavior ();
1661
+ }
1662
+
1663
+ S.Stk .push <IntegralAP<true >>(IntegralAP<true >(Result));
1664
+ return CheckFloatResult (S, OpPC, F, Status);
1665
+ }
1666
+
1611
1667
template <PrimType Name, class T = typename PrimConv<Name>::T>
1612
1668
bool CastPointerIntegral (InterpState &S, CodePtr OpPC) {
1613
1669
const Pointer &Ptr = S.Stk .pop <Pointer>();
@@ -1697,7 +1753,7 @@ inline bool Shl(InterpState &S, CodePtr OpPC) {
1697
1753
1698
1754
typename LT::AsUnsigned R;
1699
1755
LT::AsUnsigned::shiftLeft (LT::AsUnsigned::from (LHS),
1700
- LT::AsUnsigned::from (RHS), Bits, &R);
1756
+ LT::AsUnsigned::from (RHS, Bits ), Bits, &R);
1701
1757
S.Stk .push <LT>(LT::from (R));
1702
1758
return true ;
1703
1759
}
0 commit comments