History

The "open a whisky and cut your finger open" patch

Make integer constant parsing C99 compliant

Thomas Preud'homme committed 11 years ago

Commit a6c3ce61 parent ff783b93 files · +62 −37Browse files

Unified · Split

3 files
  1. tccpp.c +41 −34
  2. tests/tests2/72_long_long_constant.c +17 −0
  3. tests/tests2/Makefile +4 −3
tccpp.c+41−34
@@ -2012,7 +2012,8 @@ static void parse_number(const char *p) · 2011 unmodified lines
20122012 }
20132013 } else {
20142014 unsigned long long n, n1;
2015− int lcount, ucount;
2015+ int lcount, ucount, must_64bit;
2016+ const char *p1;
20162017
20172018 /* integer number */
20182019 *q = '\0';
@@ -2025,17 +2026,16 @@ static void parse_number(const char *p) · 6 unmodified lines
20252026 while(1) {
20262027 t = *q++;
20272028 /* no need for checks except for base 10 / 8 errors */
2028− if (t == '\0') {
2029+ if (t == '\0')
20292030 break;
2030− } else if (t >= 'a') {
2031+ else if (t >= 'a')
20312032 t = t - 'a' + 10;
2032− } else if (t >= 'A') {
2033+ else if (t >= 'A')
20332034 t = t - 'A' + 10;
2034− } else {
2035+ else
20352036 t = t - '0';
2036− if (t >= b)
2037− tcc_error("invalid digit");
2038− }
2037+ if (t >= b)
2038+ tcc_error("invalid digit");
20392039 n1 = n;
20402040 n = n * b + t;
20412041 /* detect overflow */
@@ -2043,50 +2043,57 @@ static void parse_number(const char *p) · 1 unmodified line
20432043 if (n < n1)
20442044 tcc_error("integer constant overflow");
20452045 }
2046−
2047− /* XXX: not exactly ANSI compliant */
2048− if ((n & 0xffffffff00000000LL) != 0) {
2049− if ((n >> 63) != 0)
2050− tok = TOK_CULLONG;
2051− else
2052− tok = TOK_CLLONG;
2053− } else if (n > 0x7fffffff) {
2054− tok = TOK_CUINT;
2055− } else {
2056− tok = TOK_CINT;
2057− }
2058− lcount = 0;
2059− ucount = 0;
2046+
2047+ /* Determine the characteristics (unsigned and/or 64bit) the type of
2048+ the constant must have according to the constant suffix(es) */
2049+ lcount = ucount = must_64bit = 0;
2050+ p1 = p;
20602051 for(;;) {
20612052 t = toup(ch);
20622053 if (t == 'L') {
20632054 if (lcount >= 2)
20642055 tcc_error("three 'l's in integer constant");
2056+ if (lcount && *(p - 1) != ch)
2057+ tcc_error("incorrect integer suffix: %s", p1);
20652058 lcount++;
20662059 #if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
2067− if (lcount == 2) {
2068−#endif
2069− if (tok == TOK_CINT)
2070− tok = TOK_CLLONG;
2071− else if (tok == TOK_CUINT)
2072− tok = TOK_CULLONG;
2073−#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
2074− }
2060+ if (lcount == 2)
20752061 #endif
2062+ must_64bit = 1;
20762063 ch = *p++;
20772064 } else if (t == 'U') {
20782065 if (ucount >= 1)
20792066 tcc_error("two 'u's in integer constant");
20802067 ucount++;
2081− if (tok == TOK_CINT)
2082− tok = TOK_CUINT;
2083− else if (tok == TOK_CLLONG)
2084− tok = TOK_CULLONG;
20852068 ch = *p++;
20862069 } else {
20872070 break;
20882071 }
20892072 }
2073+
2074+ /* Whether 64 bits are needed to hold the constant's value */
2075+ if (n & 0xffffffff00000000LL || must_64bit) {
2076+ tok = TOK_CLLONG;
2077+ n1 = n >> 32;
2078+ } else {
2079+ tok = TOK_CINT;
2080+ n1 = n;
2081+ }
2082+
2083+ /* Whether type must be unsigned to hold the constant's value */
2084+ if (ucount || ((n1 >> 31) && (b != 10))) {
2085+ if (tok == TOK_CLLONG)
2086+ tok = TOK_CULLONG;
2087+ else
2088+ tok = TOK_CUINT;
2089+ /* If decimal and no unsigned suffix, bump to 64 bits or throw error */
2090+ } else if (n1 >> 31) {
2091+ if (tok == TOK_CINT)
2092+ tok = TOK_CLLONG;
2093+ else
2094+ tcc_error("integer constant overflow");
2095+ }
2096+
20902097 if (tok == TOK_CINT || tok == TOK_CUINT)
20912098 tokc.ui = n;
20922099 else
tests/tests2/72_long_long_constant.c+17−0
@@ -0,0 +1,17 @@
1+#include <stdio.h>
2+
3+int main()
4+{
5+ long long int res = 0;
6+
7+ if (res < -2147483648LL) {
8+ printf("Error: 0 < -2147483648\n");
9+ return 1;
10+ }
11+ else
12+ if (2147483647LL < res) {
13+ printf("Error: 2147483647 < 0\n");
14+ return 2;
15+ }
16+ return 0;
17+}
tests/tests2/Makefile+4−3
@@ -91,6 +91,7 @@ TESTS = \ · 90 unmodified lines
9191 69_macro_param_list_err_2.test \
9292 70_floating_point_literals.test \
9393 71_macro_empty_arg.test \
94+ 72_long_long_constant.test \
9495
9596
9697 # 34_array_assignment.test -- array assignment is not in C standard
@@ -113,14 +114,14 @@ ARGS = · 16 unmodified lines
113114
114115 all test: $(filter-out $(SKIP),$(TESTS))
115116
116−%.test: %.c %.expect
117+%.test: %.c
117118 @echo Test: $*...
118119
119120 @$(TCC) -run $< $(ARGS) 2>&1 | grep -v 'warning: soft float ABI currently not supported: default to softfp' >$*.output || true
120− @diff -bu $*.expect $*.output && rm -f $*.output
121+ @diff -Nbu $*.expect $*.output && rm -f $*.output
121122
122123 @($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) 2>&1 | grep -v 'warning: soft float ABI currently not supported: default to softfp' >$*.output2 || true
123− @diff -bu $*.expect $*.output2 && rm -f $*.output2 $*.exe
124+ @diff -Nbu $*.expect $*.output2 && rm -f $*.output2 $*.exe
124125
125126 clean:
126127 rm -vf fred.txt *.output* *.exe

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t