Skip to content

Commit 7d2b569

Browse files
authored
[Sema] Handle large shift counts in GetExprRange (#68590)
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.
1 parent 5dcbf0a commit 7d2b569

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,10 @@ Bug Fixes in This Version
378378
- Fix crash in evaluating ``constexpr`` value for invalid template function.
379379
Fixes (`#68542 <https://github.com/llvm/llvm-project/issues/68542>`_)
380380

381+
- Fixed an issue when a shift count larger than ``__INT64_MAX__``, in a right
382+
shift operation, could result in missing warnings about
383+
``shift count >= width of type`` or internal compiler error.
384+
381385
Bug Fixes to Compiler Builtins
382386
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
383387

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13596,11 +13596,10 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth,
1359613596
if (std::optional<llvm::APSInt> shift =
1359713597
BO->getRHS()->getIntegerConstantExpr(C)) {
1359813598
if (shift->isNonNegative()) {
13599-
unsigned zext = shift->getZExtValue();
13600-
if (zext >= L.Width)
13599+
if (shift->uge(L.Width))
1360113600
L.Width = (L.NonNegative ? 0 : 1);
1360213601
else
13603-
L.Width -= zext;
13602+
L.Width -= shift->getZExtValue();
1360413603
}
1360513604
}
1360613605

clang/test/Sema/c2x-expr-range.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clang_cc1 -verify -fsyntax-only -std=c2x -triple=x86_64-unknown-linux %s
2+
3+
// Regression test for bug where we used to hit an assertion due to shift amount
4+
// being larger than 64 bits. We want to see a warning about too large shift
5+
// amount.
6+
void test1(int *a) {
7+
(void)(*a >> 123456789012345678901uwb <= 0); // expected-warning {{shift count >= width of type}}
8+
}
9+
10+
// Similar to test1 above, but using __uint128_t instead of __BitInt.
11+
// We want to see a warning about too large shift amount.
12+
void test2(__uint128_t *a) {
13+
(void)(*a >> ((__uint128_t)__UINT64_MAX__ + 1) <= 0); // expected-warning {{shift count >= width of type}}
14+
}

0 commit comments

Comments
 (0)