Skip to content

Commit

Permalink
[Sema] Handle large shift counts in GetExprRange (#68590)
Browse files Browse the repository at this point in the history
GetExprRange did not expect that very large shift counts when
narrowing the range based on logical right shifts. So with inputs
such as
    *a >> 123456789012345678901uwb
it would hit assertions about trying to convert a too large APInt
into uint64_t.
This patch fixes that by using the APInt value when determining if
we should reduce the range by the shift count or not.
  • Loading branch information
bjope committed Oct 10, 2023
1 parent 5dcbf0a commit 7d2b569
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,10 @@ Bug Fixes in This Version
- Fix crash in evaluating ``constexpr`` value for invalid template function.
Fixes (`#68542 <https://github.com/llvm/llvm-project/issues/68542>`_)

- Fixed an issue when a shift count larger than ``__INT64_MAX__``, in a right
shift operation, could result in missing warnings about
``shift count >= width of type`` or internal compiler error.

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13596,11 +13596,10 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
if (std::optional<llvm::APSInt> shift =
BO->getRHS()->getIntegerConstantExpr(C)) {
if (shift->isNonNegative()) {
unsigned zext = shift->getZExtValue();
if (zext >= L.Width)
if (shift->uge(L.Width))
L.Width = (L.NonNegative ? 0 : 1);
else
L.Width -= zext;
L.Width -= shift->getZExtValue();
}
}

Expand Down
14 changes: 14 additions & 0 deletions clang/test/Sema/c2x-expr-range.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -verify -fsyntax-only -std=c2x -triple=x86_64-unknown-linux %s

// Regression test for bug where we used to hit an assertion due to shift amount
// being larger than 64 bits. We want to see a warning about too large shift
// amount.
void test1(int *a) {
(void)(*a >> 123456789012345678901uwb <= 0); // expected-warning {{shift count >= width of type}}
}

// Similar to test1 above, but using __uint128_t instead of __BitInt.
// We want to see a warning about too large shift amount.
void test2(__uint128_t *a) {
(void)(*a >> ((__uint128_t)__UINT64_MAX__ + 1) <= 0); // expected-warning {{shift count >= width of type}}
}

0 comments on commit 7d2b569

Please sign in to comment.