Skip to content

Commit f460655

Browse files
committed
Lex: add support for i128 and ui128 suffixes (llvm#130993)
Microsoft's compiler supports an extension for 128-bit literals. This is referenced in `intsafe.h` which is included transitievly. When building with modules, the literal parsing causes a failure due to the missing support for the extension. To alleviate this issue, support parsing this literal, especially now that there is the BitInt extension. Take the opportunity to tighten up the code slightly by ensuring that we do not access out-of-bounds characters when lexing the token. (cherry picked from commit dcec224)
1 parent 638f45c commit f460655

File tree

5 files changed

+43
-13
lines changed

5 files changed

+43
-13
lines changed

clang/docs/ReleaseNotes.rst

+4
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,10 @@ Windows Support
13141314
to ensure compatibility with msvc. Previously strict aliasing was only disabled if the
13151315
driver mode was cl.
13161316

1317+
- Clang now can process the `i128` and `ui128` integeral suffixes when MSVC
1318+
extensions are enabled. This allows for properly processing ``intsafe.h`` in
1319+
the Windows SDK.
1320+
13171321
LoongArch Support
13181322
^^^^^^^^^^^^^^^^^
13191323

clang/include/clang/Lex/LiteralSupport.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ class NumericLiteralParser {
8282
bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk
8383
bool isBitInt : 1; // 1wb, 1uwb (C23) or 1__wb, 1__uwb (Clang extension in C++
8484
// mode)
85-
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
86-
85+
uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, i64, or
86+
// i128.
8787

8888
bool isFixedPointLiteral() const {
8989
return (saw_period || saw_exponent) && saw_fixed_point_suffix;

clang/lib/Lex/LiteralSupport.cpp

+9-5
Original file line numberDiff line numberDiff line change
@@ -1071,8 +1071,8 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
10711071
continue;
10721072
case 'i':
10731073
case 'I':
1074-
if (LangOpts.MicrosoftExt && !isFPConstant) {
1075-
// Allow i8, i16, i32, and i64. First, look ahead and check if
1074+
if (LangOpts.MicrosoftExt && s + 1 < ThisTokEnd && !isFPConstant) {
1075+
// Allow i8, i16, i32, i64, and i128. First, look ahead and check if
10761076
// suffixes are Microsoft integers and not the imaginary unit.
10771077
uint8_t Bits = 0;
10781078
size_t ToSkip = 0;
@@ -1082,19 +1082,23 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
10821082
ToSkip = 2;
10831083
break;
10841084
case '1':
1085-
if (s[2] == '6') { // i16 suffix
1085+
if (s + 2 < ThisTokEnd && s[2] == '6') { // i16 suffix
10861086
Bits = 16;
10871087
ToSkip = 3;
1088+
} else if (s + 3 < ThisTokEnd && s[2] == '2' &&
1089+
s[3] == '8') { // i128 suffix
1090+
Bits = 128;
1091+
ToSkip = 4;
10881092
}
10891093
break;
10901094
case '3':
1091-
if (s[2] == '2') { // i32 suffix
1095+
if (s + 2 < ThisTokEnd && s[2] == '2') { // i32 suffix
10921096
Bits = 32;
10931097
ToSkip = 3;
10941098
}
10951099
break;
10961100
case '6':
1097-
if (s[2] == '4') { // i64 suffix
1101+
if (s + 2 < ThisTokEnd && s[2] == '4') { // i64 suffix
10981102
Bits = 64;
10991103
ToSkip = 3;
11001104
}

clang/lib/Sema/SemaExpr.cpp

+12-4
Original file line numberDiff line numberDiff line change
@@ -4360,10 +4360,18 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) {
43604360
// to get the integer value from an overly-wide APInt is *extremely*
43614361
// expensive, so the naive approach of assuming
43624362
// llvm::IntegerType::MAX_INT_BITS is a big performance hit.
4363-
unsigned BitsNeeded =
4364-
Literal.isBitInt ? llvm::APInt::getSufficientBitsNeeded(
4365-
Literal.getLiteralDigits(), Literal.getRadix())
4366-
: Context.getTargetInfo().getIntMaxTWidth();
4363+
unsigned BitsNeeded = Context.getTargetInfo().getIntMaxTWidth();
4364+
if (Literal.isBitInt)
4365+
BitsNeeded = llvm::APInt::getSufficientBitsNeeded(
4366+
Literal.getLiteralDigits(), Literal.getRadix());
4367+
if (Literal.MicrosoftInteger) {
4368+
if (Literal.MicrosoftInteger == 128 &&
4369+
!Context.getTargetInfo().hasInt128Type())
4370+
PP.Diag(Tok.getLocation(), diag::err_integer_literal_too_large)
4371+
<< Literal.isUnsigned;
4372+
BitsNeeded = Literal.MicrosoftInteger;
4373+
}
4374+
43674375
llvm::APInt ResultVal(BitsNeeded, 0);
43684376

43694377
if (Literal.GetIntegerValue(ResultVal)) {

clang/test/Lexer/ms-extensions.c

+16-2
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,30 @@ __int64 w = 0x43ui64;
1313
__int64 z = 9Li64; // expected-error {{invalid suffix}}
1414
__int64 q = 10lli64; // expected-error {{invalid suffix}}
1515

16-
__complex double c1 = 1i;
17-
__complex double c2 = 1.0i;
16+
__complex double c1 = 1i; // GNU extension
17+
__complex double c2 = 1.0i; // GNU extension
1818
__complex float c3 = 1.0if;
1919

20+
#define UINT128_MAX 0xffffffffffffffffffffffffffffffffui128
2021
#define ULLONG_MAX 0xffffffffffffffffui64
2122
#define UINT 0xffffffffui32
2223
#define USHORT 0xffffui16
2324
#define UCHAR 0xffui8
2425

26+
#define INT128_MAX 170141183460469231731687303715884105727i128
27+
2528
void a(void) {
29+
#if __SIZEOF_INT128__
30+
__int128 j = UINT128_MAX;
31+
__int128 k = INT128_MAX;
32+
#else
33+
int j = UINT128_MAX;
34+
// expected-warning@-1{{implicit conversion from 'unsigned __int128' to 'int' changes value from 340282366920938463463374607431768211455 to -1}}
35+
// expected-error@-2{{integer literal is too large to be represented in any integer type}}
36+
int k = INT128_MAX;
37+
// expected-warning@-1{{implicit conversion from '__int128' to 'int' changes value from 170141183460469231731687303715884105727 to -1}}
38+
// expected-error@-2{{integer literal is too large to be represented in any signed integer type}}
39+
#endif
2640
unsigned long long m = ULLONG_MAX;
2741
unsigned int n = UINT;
2842
unsigned short s = USHORT;

0 commit comments

Comments
 (0)