@@ -2579,6 +2579,42 @@ inline bool Shl(InterpState &S, CodePtr OpPC) {
25792579 return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS);
25802580}
25812581
2582+ static inline bool ShiftFixedPoint (InterpState &S, CodePtr OpPC, bool Left) {
2583+ const auto &RHS = S.Stk .pop <FixedPoint>();
2584+ const auto &LHS = S.Stk .pop <FixedPoint>();
2585+ llvm::FixedPointSemantics LHSSema = LHS.getSemantics ();
2586+
2587+ unsigned ShiftBitWidth =
2588+ LHSSema.getWidth () - (unsigned )LHSSema.hasUnsignedPadding () - 1 ;
2589+
2590+ // Embedded-C 4.1.6.2.2:
2591+ // The right operand must be nonnegative and less than the total number
2592+ // of (nonpadding) bits of the fixed-point operand ...
2593+ if (RHS.isNegative ()) {
2594+ S.CCEDiag (S.Current ->getLocation (OpPC), diag::note_constexpr_negative_shift)
2595+ << RHS.toAPSInt ();
2596+ } else if (static_cast <unsigned >(RHS.toAPSInt ().getLimitedValue (
2597+ ShiftBitWidth)) != RHS.toAPSInt ()) {
2598+ const Expr *E = S.Current ->getExpr (OpPC);
2599+ S.CCEDiag (E, diag::note_constexpr_large_shift)
2600+ << RHS.toAPSInt () << E->getType () << ShiftBitWidth;
2601+ }
2602+
2603+ FixedPoint Result;
2604+ if (Left) {
2605+ if (FixedPoint::shiftLeft (LHS, RHS, ShiftBitWidth, &Result) &&
2606+ !handleFixedPointOverflow (S, OpPC, Result))
2607+ return false ;
2608+ } else {
2609+ if (FixedPoint::shiftRight (LHS, RHS, ShiftBitWidth, &Result) &&
2610+ !handleFixedPointOverflow (S, OpPC, Result))
2611+ return false ;
2612+ }
2613+
2614+ S.Stk .push <FixedPoint>(Result);
2615+ return true ;
2616+ }
2617+
25822618// ===----------------------------------------------------------------------===//
25832619// NoRet
25842620// ===----------------------------------------------------------------------===//
0 commit comments