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
2012 }2012 }
2013 } else {2013 } else {
2014 unsigned long long n, n1;2014 unsigned long long n, n1;
2015 int lcount, ucount;2015 int lcount, ucount, must_64bit;
2016 const char *p1;
2016 2017
2017 /* integer number */2018 /* integer number */
2018 *q = '\0';2019 *q = '\0';
@@ -2025,17 +2026,16 @@ static void parse_number(const char *p) · 6 unmodified lines
2025 while(1) {2026 while(1) {
2026 t = *q++;2027 t = *q++;
2027 /* no need for checks except for base 10 / 8 errors */2028 /* no need for checks except for base 10 / 8 errors */
2028 if (t == '\0') {2029 if (t == '\0')
2029 break;2030 break;
2030 } else if (t >= 'a') {2031 else if (t >= 'a')
2031 t = t - 'a' + 10;2032 t = t - 'a' + 10;
2032 } else if (t >= 'A') {2033 else if (t >= 'A')
2033 t = t - 'A' + 10;2034 t = t - 'A' + 10;
2034 } else {2035 else
2035 t = t - '0';2036 t = t - '0';
2036 if (t >= b)2037 if (t >= b)
2037 tcc_error("invalid digit");2038 tcc_error("invalid digit");
2038 }
2039 n1 = n;2039 n1 = n;
2040 n = n * b + t;2040 n = n * b + t;
2041 /* detect overflow */2041 /* detect overflow */
@@ -2043,50 +2043,57 @@ static void parse_number(const char *p) · 1 unmodified line
2043 if (n < n1)2043 if (n < n1)
2044 tcc_error("integer constant overflow");2044 tcc_error("integer constant overflow");
2045 }2045 }
2046 2046
2047 /* XXX: not exactly ANSI compliant */2047 /* Determine the characteristics (unsigned and/or 64bit) the type of
2048 if ((n & 0xffffffff00000000LL) != 0) {2048 the constant must have according to the constant suffix(es) */
2049 if ((n >> 63) != 0)2049 lcount = ucount = must_64bit = 0;
2050 tok = TOK_CULLONG;2050 p1 = p;
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;
2060 for(;;) {2051 for(;;) {
2061 t = toup(ch);2052 t = toup(ch);
2062 if (t == 'L') {2053 if (t == 'L') {
2063 if (lcount >= 2)2054 if (lcount >= 2)
2064 tcc_error("three 'l's in integer constant");2055 tcc_error("three 'l's in integer constant");
2056 if (lcount && *(p - 1) != ch)
2057 tcc_error("incorrect integer suffix: %s", p1);
2065 lcount++;2058 lcount++;
2066#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE2059#if !defined TCC_TARGET_X86_64 || defined TCC_TARGET_PE
2067 if (lcount == 2) {2060 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 }
2075#endif2061#endif
2062 must_64bit = 1;
2076 ch = *p++;2063 ch = *p++;
2077 } else if (t == 'U') {2064 } else if (t == 'U') {
2078 if (ucount >= 1)2065 if (ucount >= 1)
2079 tcc_error("two 'u's in integer constant");2066 tcc_error("two 'u's in integer constant");
2080 ucount++;2067 ucount++;
2081 if (tok == TOK_CINT)
2082 tok = TOK_CUINT;
2083 else if (tok == TOK_CLLONG)
2084 tok = TOK_CULLONG;
2085 ch = *p++;2068 ch = *p++;
2086 } else {2069 } else {
2087 break;2070 break;
2088 }2071 }
2089 }2072 }
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
2090 if (tok == TOK_CINT || tok == TOK_CUINT)2097 if (tok == TOK_CINT || tok == TOK_CUINT)
2091 tokc.ui = n;2098 tokc.ui = n;
2092 else2099 else
tests/tests2/72_long_long_constant.c+17−0
@@ -0,0 +1,17 @@
1#include <stdio.h>
2
3int 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
91 69_macro_param_list_err_2.test \91 69_macro_param_list_err_2.test \
92 70_floating_point_literals.test \92 70_floating_point_literals.test \
93 71_macro_empty_arg.test \93 71_macro_empty_arg.test \
94 72_long_long_constant.test \
94 95
95 96
96# 34_array_assignment.test -- array assignment is not in C standard97# 34_array_assignment.test -- array assignment is not in C standard
@@ -113,14 +114,14 @@ ARGS = · 16 unmodified lines
113 114
114all test: $(filter-out $(SKIP),$(TESTS))115all test: $(filter-out $(SKIP),$(TESTS))
115 116
116%.test: %.c %.expect117%.test: %.c
117 @echo Test: $*...118 @echo Test: $*...
118 119
119 @$(TCC) -run $< $(ARGS) 2>&1 | grep -v 'warning: soft float ABI currently not supported: default to softfp' >$*.output || true120 @$(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 $*.output121 @diff -Nbu $*.expect $*.output && rm -f $*.output
121 122
122 @($(TCC) $< -o $*.exe && ./$*.exe $(ARGS)) 2>&1 | grep -v 'warning: soft float ABI currently not supported: default to softfp' >$*.output2 || true123 @($(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 $*.exe124 @diff -Nbu $*.expect $*.output2 && rm -f $*.output2 $*.exe
124 125
125clean:126clean:
126 rm -vf fred.txt *.output* *.exe127 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