-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] Fixes inf loop parsing fixed point literal #83071
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-clang Author: None (PiJoules) ChangesClang was incorrectly finding the start of the exponent in a fixed point hex literal. It would unconditionally find the first Full diff: https://github.com/llvm/llvm-project/pull/83071.diff 3 Files Affected:
diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp
index 571a984884029d..438c6d772e6e04 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -1513,8 +1513,10 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) {
: APFloat::opInvalidOp;
}
-static inline bool IsExponentPart(char c) {
- return c == 'p' || c == 'P' || c == 'e' || c == 'E';
+static inline bool IsExponentPart(char c, bool isHex) {
+ if (isHex)
+ return c == 'p' || c == 'P';
+ return c == 'e' || c == 'E';
}
bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) {
@@ -1533,7 +1535,8 @@ bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Sc
if (saw_exponent) {
const char *Ptr = DigitsBegin;
- while (!IsExponentPart(*Ptr)) ++Ptr;
+ while (!IsExponentPart(*Ptr, radix == 16))
+ ++Ptr;
ExponentBegin = Ptr;
++Ptr;
NegativeExponent = *Ptr == '-';
diff --git a/clang/test/Frontend/GH83050.cpp b/clang/test/Frontend/GH83050.cpp
new file mode 100644
index 00000000000000..df55d848a5fd5f
--- /dev/null
+++ b/clang/test/Frontend/GH83050.cpp
@@ -0,0 +1,11 @@
+/// This is the regression test for https://github.com/llvm/llvm-project/issues/83050.
+/// This just needs to compile.
+// RUN: %clang_cc1 -x c++ -ffixed-point -S %s -o /dev/null -triple=x86_64-linux -ffixed-point
+static constexpr unsigned short _Fract SQRT_FIRST_APPROX[12][2] = {
+ {0x1.e8p-1uhr, 0x1.0cp-2uhr}, {0x1.bap-1uhr, 0x1.28p-2uhr},
+ {0x1.94p-1uhr, 0x1.44p-2uhr}, {0x1.74p-1uhr, 0x1.6p-2uhr},
+ {0x1.6p-1uhr, 0x1.74p-2uhr}, {0x1.4ep-1uhr, 0x1.88p-2uhr},
+ {0x1.3ep-1uhr, 0x1.9cp-2uhr}, {0x1.32p-1uhr, 0x1.acp-2uhr},
+ {0x1.22p-1uhr, 0x1.c4p-2uhr}, {0x1.18p-1uhr, 0x1.d4p-2uhr},
+ {0x1.08p-1uhr, 0x1.fp-2uhr}, {0x1.04p-1uhr, 0x1.f8p-2uhr},
+};
diff --git a/clang/test/Frontend/fixed_point_declarations.c b/clang/test/Frontend/fixed_point_declarations.c
index 04ed25d227ca52..c8045767442739 100644
--- a/clang/test/Frontend/fixed_point_declarations.c
+++ b/clang/test/Frontend/fixed_point_declarations.c
@@ -125,3 +125,21 @@ long _Fract long_fract_zero = 0.0lr; // CHECK-DAG: @long_fract_
unsigned short _Fract u_short_fract_zero = 0.0uhr; // CHECK-DAG: @u_short_fract_zero = {{.*}}global i8 0, align 1
unsigned _Fract u_fract_zero = 0.0ur; // CHECK-DAG: @u_fract_zero = {{.*}}global i16 0, align 2
unsigned long _Fract u_long_fract_zero = 0.0ulr; // CHECK-DAG: @u_long_fract_zero = {{.*}}global i32 0, align 4
+
+// Hex exponent suffix with E in hex digit sequence.
+unsigned short _Fract e1 = 0x1.e8p-1uhr; // CHECK-DAG: @e1 = {{.*}}global i8 -12
+unsigned short _Fract e2 = 0x1.8ep-1uhr; // CHECK-DAG: @e2 = {{.*}}global i8 -57
+unsigned short _Fract e3 = 0x1.ep-1uhr; // CHECK-DAG: @e3 = {{.*}}global i8 -16
+unsigned _Accum e4 = 0xep-1uk; // CHECK-DAG: @e4 = {{.*}}global i32 458752
+unsigned _Accum e5 = 0xe.1p-1uk; // CHECK-DAG: @e5 = {{.*}}global i32 460800
+unsigned _Accum e6 = 0xe.ep-1uk; // CHECK-DAG: @e6 = {{.*}}global i32 487424
+unsigned _Accum e7 = 0xe.e8p-1uk; // CHECK-DAG: @e7 = {{.*}}global i32 488448
+unsigned _Accum e8 = 0xe.8ep-1uk; // CHECK-DAG: @e8 = {{.*}}global i32 476928
+unsigned short _Fract E1 = 0x1.E8p-1uhr; // CHECK-DAG: @E1 = {{.*}}global i8 -12
+unsigned short _Fract E2 = 0x1.8Ep-1uhr; // CHECK-DAG: @E2 = {{.*}}global i8 -57
+unsigned short _Fract E3 = 0x1.Ep-1uhr; // CHECK-DAG: @E3 = {{.*}}global i8 -16
+unsigned _Accum E4 = 0xEp-1uk; // CHECK-DAG: @E4 = {{.*}}global i32 458752
+unsigned _Accum E5 = 0xE.1p-1uk; // CHECK-DAG: @E5 = {{.*}}global i32 460800
+unsigned _Accum E6 = 0xE.Ep-1uk; // CHECK-DAG: @E6 = {{.*}}global i32 487424
+unsigned _Accum E7 = 0xE.E8p-1uk; // CHECK-DAG: @E7 = {{.*}}global i32 488448
+unsigned _Accum E8 = 0xE.8Ep-1uk; // CHECK-DAG: @E8 = {{.*}}global i32 476928
|
For the commit message and PR description, please consider:
|
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. Fixes llvm#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.Fixes #83050