@@ -2511,52 +2511,50 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
2511
2511
S, OpPC, LHS, RHS);
2512
2512
}
2513
2513
2514
+ if constexpr (Dir == ShiftDir::Left) {
2515
+ if (LHS.isNegative () && !S.getLangOpts ().CPlusPlus20 ) {
2516
+ // C++11 [expr.shift]p2: A signed left shift must have a non-negative
2517
+ // operand, and must not overflow the corresponding unsigned type.
2518
+ // C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
2519
+ // E1 x 2^E2 module 2^N.
2520
+ const SourceInfo &Loc = S.Current ->getSource (OpPC);
2521
+ S.CCEDiag (Loc, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt ();
2522
+ if (!S.noteUndefinedBehavior ())
2523
+ return false ;
2524
+ }
2525
+ }
2526
+
2514
2527
if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
2515
2528
return false ;
2516
2529
2517
2530
// Limit the shift amount to Bits - 1. If this happened,
2518
2531
// it has already been diagnosed by CheckShift() above,
2519
2532
// but we still need to handle it.
2520
- // Note that we have to be extra careful here since we're doing the shift in
2521
- // any case, but we need to adjust the shift amount or the way we do the shift
2522
- // for the potential error cases.
2523
2533
typename LT::AsUnsigned R;
2524
- unsigned MaxShiftAmount = LHS.bitWidth () - 1 ;
2525
2534
if constexpr (Dir == ShiftDir::Left) {
2526
- if (Compare (RHS, RT::from (MaxShiftAmount, RHS.bitWidth ())) ==
2527
- ComparisonCategoryResult::Greater) {
2528
- if (LHS.isNegative ())
2529
- R = LT::AsUnsigned::zero (LHS.bitWidth ());
2530
- else {
2531
- RHS = RT::from (LHS.countLeadingZeros (), RHS.bitWidth ());
2532
- LT::AsUnsigned::shiftLeft (LT::AsUnsigned::from (LHS),
2533
- LT::AsUnsigned::from (RHS, Bits), Bits, &R);
2534
- }
2535
- } else if (LHS.isNegative ()) {
2536
- if (LHS.isMin ()) {
2537
- R = LT::AsUnsigned::zero (LHS.bitWidth ());
2538
- } else {
2539
- // If the LHS is negative, perform the cast and invert the result.
2540
- typename LT::AsUnsigned LHSU = LT::AsUnsigned::from (-LHS);
2541
- LT::AsUnsigned::shiftLeft (LHSU, LT::AsUnsigned::from (RHS, Bits), Bits,
2542
- &R);
2543
- R = -R;
2544
- }
2545
- } else {
2546
- // The good case, a simple left shift.
2535
+ if (RHS > RT::from (Bits - 1 , RHS.bitWidth ()))
2536
+ LT::AsUnsigned::shiftLeft (LT::AsUnsigned::from (LHS),
2537
+ LT::AsUnsigned::from (Bits - 1 ), Bits, &R);
2538
+ else
2547
2539
LT::AsUnsigned::shiftLeft (LT::AsUnsigned::from (LHS),
2548
2540
LT::AsUnsigned::from (RHS, Bits), Bits, &R);
2549
- }
2550
2541
} else {
2551
- // Right shift.
2552
- if (Compare (RHS, RT::from (MaxShiftAmount, RHS.bitWidth ())) ==
2553
- ComparisonCategoryResult::Greater) {
2554
- R = LT::AsUnsigned::from (-1 );
2555
- } else {
2556
- // Do the shift on potentially signed LT, then convert to unsigned type.
2557
- LT A;
2558
- LT::shiftRight (LHS, LT::from (RHS, Bits), Bits, &A);
2559
- R = LT::AsUnsigned::from (A);
2542
+ if (RHS > RT::from (Bits - 1 , RHS.bitWidth ()))
2543
+ LT::AsUnsigned::shiftRight (LT::AsUnsigned::from (LHS),
2544
+ LT::AsUnsigned::from (Bits - 1 ), Bits, &R);
2545
+ else
2546
+ LT::AsUnsigned::shiftRight (LT::AsUnsigned::from (LHS),
2547
+ LT::AsUnsigned::from (RHS, Bits), Bits, &R);
2548
+ }
2549
+
2550
+ // We did the shift above as unsigned. Restore the sign bit if we need to.
2551
+ if constexpr (Dir == ShiftDir::Right) {
2552
+ if (LHS.isSigned () && LHS.isNegative ()) {
2553
+ typename LT::AsUnsigned SignBit;
2554
+ LT::AsUnsigned::shiftLeft (LT::AsUnsigned::from (1 , Bits),
2555
+ LT::AsUnsigned::from (Bits - 1 , Bits), Bits,
2556
+ &SignBit);
2557
+ LT::AsUnsigned::bitOr (R, SignBit, Bits, &R);
2560
2558
}
2561
2559
}
2562
2560
0 commit comments