History

Fix handling of unevaluated subexpression of const

we were emitting error messages for something like 'static int i = 2 || 1/0', even though the exception would be in the unevaluated part. This doesn't destroy const-ness, so we must accept it. This requires splitting the nocode_wanted values a bit more, so that nocode_wanted due to const_wanted can be differentiated from nocode_wanted due to non-evaluation.

Michael Matz committed 6 years ago

Commit 4a70b2b1 parent 38776184 files · +32 −18Browse files

Unified · Split

4 files
  1. tccgen.c +5 −4
  2. tests/tcctest.c +6 −0
  3. tests/tests2/60_errors_and_warnings.c +4 −0
  4. tests/tests2/60_errors_and_warnings.expect +17 −14
tccgen.c+5−4
@@ -53,6 +53,7 @@ static SValue _vstack[1 + VSTACK_SIZE]; · 52 unmodified lines
5353
5454 ST_DATA int const_wanted; /* true if constant wanted */
5555 ST_DATA int nocode_wanted; /* no code generation wanted */
56+#define unevalmask 0xffff /* unevaluated subexpression */
5657 #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
5758 #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */
5859
@@ -2273,7 +2274,7 @@ static void gen_opic(int op) · 2214 unmodified lines
22732274 case TOK_UMOD:
22742275 /* if division by zero, generate explicit division */
22752276 if (l2 == 0) {
2276− if (const_wanted)
2277+ if (const_wanted && !(nocode_wanted & unevalmask))
22772278 tcc_error("division by zero in constant");
22782279 goto general_case;
22792280 }
@@ -5104,7 +5105,7 @@ ST_FUNC void unary(void) · 2824 unmodified lines
51045105 }
51055106 } else if (tok == '{') {
51065107 int saved_nocode_wanted = nocode_wanted;
5107− if (const_wanted)
5108+ if (const_wanted && !(nocode_wanted & unevalmask))
51085109 tcc_error("expected constant");
51095110 /* save all registers */
51105111 save_regs(0);
@@ -6152,9 +6153,9 @@ ST_FUNC void gexpr(void) · 1041 unmodified lines
61526153 static void expr_const1(void)
61536154 {
61546155 const_wanted++;
6155− nocode_wanted++;
6156+ nocode_wanted += unevalmask + 1;
61566157 expr_cond();
6157− nocode_wanted--;
6158+ nocode_wanted -= unevalmask + 1;
61586159 const_wanted--;
61596160 }
61606161
tests/tcctest.c+6−0
@@ -950,6 +950,8 @@ void expr2_test() · 949 unmodified lines
950950 printf("res= %d %d\n", a, b);
951951 }
952952
953+int const_len_ar[sizeof(1/0)]; /* div-by-zero, but in unevaluated context */
954+
953955 void constant_expr_test()
954956 {
955957 int a;
@@ -958,6 +960,7 @@ void constant_expr_test() · 2 unmodified lines
958960 printf("%d\n", a * 16);
959961 printf("%d\n", a * 1);
960962 printf("%d\n", a + 0);
963+ printf("%d\n", sizeof(const_len_ar));
961964 }
962965
963966 int tab4[10];
@@ -1845,6 +1848,8 @@ arrtype2 sinit22 = {5,6,7}; · 881 unmodified lines
18451848 int sinit23[2] = { "astring" ? sizeof("astring") : -1,
18461849 &sinit23 ? 42 : -1 };
18471850
1851+int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */
1852+
18481853 extern int external_inited = 42;
18491854
18501855 void init_test(void)
@@ -1959,6 +1964,7 @@ void init_test(void) · 108 unmodified lines
19591964 printf("arrtype6: %d\n", sizeof(arrtype2));
19601965
19611966 printf("sinit23= %d %d\n", sinit23[0], sinit23[1]);
1967+ printf("sinit24=%d\n", sinit24);
19621968 printf("linit18= %d %d\n", linit18[0], linit18[1]);
19631969 }
19641970
tests/tests2/60_errors_and_warnings.c+4−0
@@ -151,6 +151,10 @@ int ga = 0.42 { 2 }; · 150 unmodified lines
151151 struct S { int a, b; };
152152 struct T { struct S x; };
153153 struct T gt = { 42 a: 1, 43 };
154+#elif defined test_invalid_4
155+enum E {
156+ x = 1 / 0
157+};
154158 #elif defined test_conflicting_types
155159 int i;
156160 void foo(void) {
tests/tests2/60_errors_and_warnings.expect+17−14
@@ -72,37 +72,40 @@ · 71 unmodified lines
7272 [test_invalid_3]
7373 60_errors_and_warnings.c:153: error: ',' expected (got "a")
7474
75+[test_invalid_4]
76+60_errors_and_warnings.c:157: error: division by zero in constant
77+
7578 [test_conflicting_types]
76−60_errors_and_warnings.c:159: error: incompatible types for redefinition of 'i'
79+60_errors_and_warnings.c:163: error: incompatible types for redefinition of 'i'
7780
7881 [test_nested_types]
79−60_errors_and_warnings.c:166: error: struct/union/enum already defined
82+60_errors_and_warnings.c:170: error: struct/union/enum already defined
8083
8184 [test_vla_1]
82−60_errors_and_warnings.c:173: error: need explicit inner array size in VLAs
85+60_errors_and_warnings.c:177: error: need explicit inner array size in VLAs
8386
8487 [test_invalid_alignas]
85−60_errors_and_warnings.c:177: error: identifier expected
88+60_errors_and_warnings.c:181: error: identifier expected
8689
8790 [test_static_assert]
88−60_errors_and_warnings.c:183: error: "ONE is not 1"
91+60_errors_and_warnings.c:187: error: "ONE is not 1"
8992
9093 [test_void_array]
91−60_errors_and_warnings.c:186: error: declaration of an array of incomplete type elements
94+60_errors_and_warnings.c:190: error: declaration of an array of incomplete type elements
9295
9396 [test_incomplete_enum_array]
94−60_errors_and_warnings.c:189: error: declaration of an array of incomplete type elements
97+60_errors_and_warnings.c:193: error: declaration of an array of incomplete type elements
9598
9699 [test_incomplete_struct_array]
97−60_errors_and_warnings.c:192: error: declaration of an array of incomplete type elements
100+60_errors_and_warnings.c:196: error: declaration of an array of incomplete type elements
98101
99102 [test_const_fun_array]
100−60_errors_and_warnings.c:196: error: declaration of an array of functions
103+60_errors_and_warnings.c:200: error: declaration of an array of functions
101104
102105 [test_incomplete_array_array]
103106
104107 [test_extern_array]
105−60_errors_and_warnings.c:212: error: incompatible types for redefinition of 'x'
108+60_errors_and_warnings.c:216: error: incompatible types for redefinition of 'x'
106109
107110 [test_func_1]
108111 hello: a = 123
@@ -111,17 +114,17 @@ hello: a = 123 · 2 unmodified lines
111114 hello: a = 123
112115
113116 [test_func_3]
114−60_errors_and_warnings.c:242: warning: static storage ignored for redefinition of 'hello'
117+60_errors_and_warnings.c:246: warning: static storage ignored for redefinition of 'hello'
115118 hello: a = 123
116119
117120 [test_func_4]
118121 hello: a = 123
119122
120123 [test_func_5]
121−60_errors_and_warnings.c:242: error: incompatible types for redefinition of 'hello'
124+60_errors_and_warnings.c:246: error: incompatible types for redefinition of 'hello'
122125
123126 [test_func_6]
124−60_errors_and_warnings.c:230: error: function without file scope cannot be static
127+60_errors_and_warnings.c:234: error: function without file scope cannot be static
125128
126129 [test_var_1]
127130 main : 1 ; 1
@@ -134,6 +137,6 @@ main : 2 ; 2 · 6 unmodified lines
134137 bar : 3 ; 3
135138
136139 [test_var_3]
137−60_errors_and_warnings.c:274: error: incompatible types for redefinition of 'xxx'
140+60_errors_and_warnings.c:278: error: incompatible types for redefinition of 'xxx'
138141
139142 [test_var_4]

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