Skip to content

Commit 26b6f60

Browse files
committed
[clang] Add fix for GH issue 83050
Clang was incorrectly finding the start of the exponent in a fixed point hex literal. It would unconditionally find the first `e/E/p/P` in a constant regardless of if it were hex or not and parser the remaining digits as an APInt. In a debug build, this would be caught by an assertion, but in a release build, the assertion is removed and we'd end up in an infinite loop.
1 parent deaf53e commit 26b6f60

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

clang/lib/Lex/LiteralSupport.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,8 +1513,10 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
15131513
: APFloat::opInvalidOp;
15141514
}
15151515

1516-
static inline bool IsExponentPart(char c) {
1517-
return c == 'p' || c == 'P' || c == 'e' || c == 'E';
1516+
static inline bool IsExponentPart(char c, bool isHex) {
1517+
if (isHex)
1518+
return c == 'p' || c == 'P';
1519+
return c == 'e' || c == 'E';
15181520
}
15191521

15201522
bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) {
@@ -1533,7 +1535,8 @@ bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Sc
15331535
if (saw_exponent) {
15341536
const char *Ptr = DigitsBegin;
15351537

1536-
while (!IsExponentPart(*Ptr)) ++Ptr;
1538+
while (!IsExponentPart(*Ptr, radix == 16))
1539+
++Ptr;
15371540
ExponentBegin = Ptr;
15381541
++Ptr;
15391542
NegativeExponent = *Ptr == '-';

clang/test/Frontend/GH83050.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// This is the regression test for https://github.com/llvm/llvm-project/issues/83050.
2+
/// This just needs to compile.
3+
// RUN: %clang_cc1 -x c++ -ffixed-point -S %s -o /dev/null -triple=x86_64-linux -ffixed-point
4+
static constexpr unsigned short _Fract SQRT_FIRST_APPROX[12][2] = {
5+
{0x1.e8p-1uhr, 0x1.0cp-2uhr}, {0x1.bap-1uhr, 0x1.28p-2uhr},
6+
{0x1.94p-1uhr, 0x1.44p-2uhr}, {0x1.74p-1uhr, 0x1.6p-2uhr},
7+
{0x1.6p-1uhr, 0x1.74p-2uhr}, {0x1.4ep-1uhr, 0x1.88p-2uhr},
8+
{0x1.3ep-1uhr, 0x1.9cp-2uhr}, {0x1.32p-1uhr, 0x1.acp-2uhr},
9+
{0x1.22p-1uhr, 0x1.c4p-2uhr}, {0x1.18p-1uhr, 0x1.d4p-2uhr},
10+
{0x1.08p-1uhr, 0x1.fp-2uhr}, {0x1.04p-1uhr, 0x1.f8p-2uhr},
11+
};

clang/test/Frontend/fixed_point_declarations.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,21 @@ long _Fract long_fract_zero = 0.0lr; // CHECK-DAG: @long_fract_
125125
unsigned short _Fract u_short_fract_zero = 0.0uhr; // CHECK-DAG: @u_short_fract_zero = {{.*}}global i8 0, align 1
126126
unsigned _Fract u_fract_zero = 0.0ur; // CHECK-DAG: @u_fract_zero = {{.*}}global i16 0, align 2
127127
unsigned long _Fract u_long_fract_zero = 0.0ulr; // CHECK-DAG: @u_long_fract_zero = {{.*}}global i32 0, align 4
128+
129+
// Hex exponent suffix with E in hex digit sequence.
130+
unsigned short _Fract e1 = 0x1.e8p-1uhr; // CHECK-DAG: @e1 = {{.*}}global i8 -12
131+
unsigned short _Fract e2 = 0x1.8ep-1uhr; // CHECK-DAG: @e2 = {{.*}}global i8 -57
132+
unsigned short _Fract e3 = 0x1.ep-1uhr; // CHECK-DAG: @e3 = {{.*}}global i8 -16
133+
unsigned _Accum e4 = 0xep-1uk; // CHECK-DAG: @e4 = {{.*}}global i32 458752
134+
unsigned _Accum e5 = 0xe.1p-1uk; // CHECK-DAG: @e5 = {{.*}}global i32 460800
135+
unsigned _Accum e6 = 0xe.ep-1uk; // CHECK-DAG: @e6 = {{.*}}global i32 487424
136+
unsigned _Accum e7 = 0xe.e8p-1uk; // CHECK-DAG: @e7 = {{.*}}global i32 488448
137+
unsigned _Accum e8 = 0xe.8ep-1uk; // CHECK-DAG: @e8 = {{.*}}global i32 476928
138+
unsigned short _Fract E1 = 0x1.E8p-1uhr; // CHECK-DAG: @E1 = {{.*}}global i8 -12
139+
unsigned short _Fract E2 = 0x1.8Ep-1uhr; // CHECK-DAG: @E2 = {{.*}}global i8 -57
140+
unsigned short _Fract E3 = 0x1.Ep-1uhr; // CHECK-DAG: @E3 = {{.*}}global i8 -16
141+
unsigned _Accum E4 = 0xEp-1uk; // CHECK-DAG: @E4 = {{.*}}global i32 458752
142+
unsigned _Accum E5 = 0xE.1p-1uk; // CHECK-DAG: @E5 = {{.*}}global i32 460800
143+
unsigned _Accum E6 = 0xE.Ep-1uk; // CHECK-DAG: @E6 = {{.*}}global i32 487424
144+
unsigned _Accum E7 = 0xE.E8p-1uk; // CHECK-DAG: @E7 = {{.*}}global i32 488448
145+
unsigned _Accum E8 = 0xE.8Ep-1uk; // CHECK-DAG: @E8 = {{.*}}global i32 476928

0 commit comments

Comments
 (0)