aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorTimm Bäder <tbaeder@redhat.com>2024-12-14 06:28:12 +0100
committerTimm Bäder <tbaeder@redhat.com>2024-12-14 06:28:12 +0100
commita6636ce4d124176856c3913d4bf6c3ceff1f5a1f (patch)
tree7d57567a1a13eef506b535d072431f7c1d5b0b4e /clang/lib
parent49c2207f21c0922aedb6c70471f8ea068977eb30 (diff)
downloadllvm-a6636ce4d124176856c3913d4bf6c3ceff1f5a1f.zip
llvm-a6636ce4d124176856c3913d4bf6c3ceff1f5a1f.tar.gz
llvm-a6636ce4d124176856c3913d4bf6c3ceff1f5a1f.tar.bz2
Revert "[clang][bytecode] Fix some shift edge cases (#119895)"
This reverts commit 49c2207f21c0922aedb6c70471f8ea068977eb30. This breaks on big-endian, again: https://lab.llvm.org/buildbot/#/builders/154/builds/9018
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ByteCode/Integral.h7
-rw-r--r--clang/lib/AST/ByteCode/Interp.h68
2 files changed, 35 insertions, 40 deletions
diff --git a/clang/lib/AST/ByteCode/Integral.h b/clang/lib/AST/ByteCode/Integral.h
index 13fdb53..2658579 100644
--- a/clang/lib/AST/ByteCode/Integral.h
+++ b/clang/lib/AST/ByteCode/Integral.h
@@ -179,10 +179,7 @@ public:
unsigned countLeadingZeros() const {
if constexpr (!Signed)
return llvm::countl_zero<ReprT>(V);
- if (isPositive())
- return llvm::countl_zero<typename AsUnsigned::ReprT>(
- static_cast<typename AsUnsigned::ReprT>(V));
- llvm_unreachable("Don't call countLeadingZeros() on negative values.");
+ llvm_unreachable("Don't call countLeadingZeros() on signed types.");
}
Integral truncate(unsigned TruncBits) const {
@@ -213,7 +210,7 @@ public:
return Integral(Value.V);
}
- static Integral zero(unsigned BitWidth = 0) { return from(0); }
+ static Integral zero() { return from(0); }
template <typename T> static Integral from(T Value, unsigned NumBits) {
return Integral(Value);
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index f085f96..cdf05e3 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2511,52 +2511,50 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
S, OpPC, LHS, RHS);
}
+ if constexpr (Dir == ShiftDir::Left) {
+ if (LHS.isNegative() && !S.getLangOpts().CPlusPlus20) {
+ // C++11 [expr.shift]p2: A signed left shift must have a non-negative
+ // operand, and must not overflow the corresponding unsigned type.
+ // C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
+ // E1 x 2^E2 module 2^N.
+ const SourceInfo &Loc = S.Current->getSource(OpPC);
+ S.CCEDiag(Loc, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
+ if (!S.noteUndefinedBehavior())
+ return false;
+ }
+ }
+
if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
return false;
// Limit the shift amount to Bits - 1. If this happened,
// it has already been diagnosed by CheckShift() above,
// but we still need to handle it.
- // Note that we have to be extra careful here since we're doing the shift in
- // any case, but we need to adjust the shift amount or the way we do the shift
- // for the potential error cases.
typename LT::AsUnsigned R;
- unsigned MaxShiftAmount = LHS.bitWidth() - 1;
if constexpr (Dir == ShiftDir::Left) {
- if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
- ComparisonCategoryResult::Greater) {
- if (LHS.isNegative())
- R = LT::AsUnsigned::zero(LHS.bitWidth());
- else {
- RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
- LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
- LT::AsUnsigned::from(RHS, Bits), Bits, &R);
- }
- } else if (LHS.isNegative()) {
- if (LHS.isMin()) {
- R = LT::AsUnsigned::zero(LHS.bitWidth());
- } else {
- // If the LHS is negative, perform the cast and invert the result.
- typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
- LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS, Bits), Bits,
- &R);
- R = -R;
- }
- } else {
- // The good case, a simple left shift.
+ if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
+ LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
+ LT::AsUnsigned::from(Bits - 1), Bits, &R);
+ else
LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
LT::AsUnsigned::from(RHS, Bits), Bits, &R);
- }
} else {
- // Right shift.
- if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
- ComparisonCategoryResult::Greater) {
- R = LT::AsUnsigned::from(-1);
- } else {
- // Do the shift on potentially signed LT, then convert to unsigned type.
- LT A;
- LT::shiftRight(LHS, LT::from(RHS, Bits), Bits, &A);
- R = LT::AsUnsigned::from(A);
+ if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
+ LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
+ LT::AsUnsigned::from(Bits - 1), Bits, &R);
+ else
+ LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
+ LT::AsUnsigned::from(RHS, Bits), Bits, &R);
+ }
+
+ // We did the shift above as unsigned. Restore the sign bit if we need to.
+ if constexpr (Dir == ShiftDir::Right) {
+ if (LHS.isSigned() && LHS.isNegative()) {
+ typename LT::AsUnsigned SignBit;
+ LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(1, Bits),
+ LT::AsUnsigned::from(Bits - 1, Bits), Bits,
+ &SignBit);
+ LT::AsUnsigned::bitOr(R, SignBit, Bits, &R);
}
}