Skip to content

Commit c34071e

Browse files
authored
Merge pull request #10253 from compnerd/ui128
Lex: add support for `i128` and `ui128` suffixes (llvm#130993)
2 parents 162ee50 + f460655 commit c34071e

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)