https://github.com/AdityaOP007 created https://github.com/llvm/llvm-project/pull/212737
# [Clang] Fix overflow checking for Microsoft integer literals #212731 ## Summary This PR fixes incorrect overflow handling for explicitly-sized Microsoft integer literals (`i8`, `i16`, `i32`, and `i64`). Previously, Clang constrained the temporary parsing `APInt` to the width specified by the Microsoft suffix before performing semantic overflow checks. As a result, decimal literals such as `128i8` and `255i8` were accepted because they fit within an unsigned 8-bit representation, even though they exceed the valid range of a signed `i8`. These values were then silently truncated during constant evaluation, leading to incorrect results. This change preserves the full parsed value during integer literal parsing and performs an explicit bounds check against the target Microsoft integer type before any truncation occurs. This ensures that overflowing decimal literals are diagnosed correctly while preserving the existing behavior for unsigned and non-decimal Microsoft integer literals. ## Changes * Preserve the full parsed integer value by avoiding premature narrowing of the parsing `APInt`. * Add an explicit semantic overflow check for Microsoft integer literals before truncation. * Reuse the existing `err_integer_literal_too_large` diagnostic. * Keep the implementation localized to the Microsoft integer literal handling path without affecting standard C/C++ integer literal semantics. * Add regression tests covering valid values, signed overflow cases, truncation behavior, and constant evaluation. ## Example ### Before ```cpp static_assert(-255i8 == -255, ""); ``` The literal was accepted, silently truncated, and produced an incorrect constant value. ### After ```cpp static_assert(-255i8 == -255, ""); ``` Clang now correctly emits: ``` error: integer literal is too large to be represented in any integer type ``` instead of silently truncating the value. ## Testing Added regression tests covering: * Valid Microsoft integer literals (`0i8`, `1i8`, `127i8`) * Signed overflow (`128i8`, `255i8`, `256i8`) * Constant evaluation involving overflowing literals * Unsigned Microsoft integer literals (`255ui8`) * Non-decimal Microsoft integer literals (for example, `0xFFi8`) to verify existing behavior remains unchanged. ## Output ### Before ```text 128i8 -> Accepted 255i8 -> Accepted -255i8 -> Incorrectly evaluated after truncation ``` ### After ```text 128i8 -> error: integer literal is too large to be represented in any integer type 255i8 -> error: integer literal is too large to be represented in any integer type -255i8 -> error: integer literal is too large to be represented in any integer type ``` ### Files Changed * `clang/lib/Sema/SemaExpr.cpp` * `clang/test/SemaCXX/ms_integer_suffix.cpp` >From fdc54e566c9f23477e390b48ab80a9eca3bd1dd6 Mon Sep 17 00:00:00 2001 From: Aditya Prakash Jha <[email protected]> Date: Wed, 29 Jul 2026 16:31:16 +0530 Subject: [PATCH] [Clang] Fix overflow checking for Microsoft integer literals --- clang/lib/Sema/SemaExpr.cpp | 9 ++++++++- clang/test/SemaCXX/ms_integer_suffix.cpp | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 67d9ac4ad5cff..3211487d44959 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4072,7 +4072,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { !Context.getTargetInfo().hasInt128Type()) PP.Diag(Tok.getLocation(), diag::err_integer_literal_too_large) << Literal.isUnsigned; - BitsNeeded = Literal.MicrosoftInteger; + BitsNeeded = std::max(BitsNeeded, (unsigned)Literal.MicrosoftInteger); } llvm::APInt ResultVal(BitsNeeded, 0); @@ -4114,6 +4114,13 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { Ty = Context.getIntTypeForBitwidth(Width, /*Signed=*/!Literal.isUnsigned); } + + bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10; + if (!ResultVal.isIntN(Width) || + (!AllowUnsigned && ResultVal[Width - 1] != 0)) { + Diag(Tok.getLocation(), diag::err_integer_literal_too_large) + << Literal.isUnsigned; + } } // Bit-precise integer literals are automagically-sized based on the diff --git a/clang/test/SemaCXX/ms_integer_suffix.cpp b/clang/test/SemaCXX/ms_integer_suffix.cpp index aa2f13099d3b8..46b18dcfc5ed2 100644 --- a/clang/test/SemaCXX/ms_integer_suffix.cpp +++ b/clang/test/SemaCXX/ms_integer_suffix.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -fms-extensions -verify %s -// expected-no-diagnostics #ifdef __SIZEOF_INT8__ static_assert(sizeof(0i8) == __SIZEOF_INT8__, ""); @@ -8,6 +7,18 @@ constexpr int f(char) { return 1; } constexpr int f(signed char) { return 2; } static_assert(f(0i8) == 1, ""); + +constexpr auto v1 = 127i8; +constexpr auto v2 = 128i8; // expected-error {{integer literal is too large to be represented in any integer type}} +constexpr auto v3 = 255i8; // expected-error {{integer literal is too large to be represented in any integer type}} +constexpr auto v4 = 256i8; // expected-error {{integer literal is too large to be represented in any integer type}} +constexpr auto v5 = -128i8; // expected-error {{integer literal is too large to be represented in any integer type}} +constexpr auto v6 = -255i8; // expected-error {{integer literal is too large to be represented in any integer type}} +static_assert(-255i8 == -255, ""); // expected-error {{integer literal is too large to be represented in any integer type}} + +constexpr auto v7 = 0xFFi8; +constexpr auto v8 = 255ui8; + #endif #ifdef __SIZEOF_INT16__ static_assert(sizeof(0i16) == __SIZEOF_INT16__, ""); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
