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.
Unified · Split
| @@ -53,6 +53,7 @@ static SValue _vstack[1 + VSTACK_SIZE]; · 52 unmodified lines | |||
| 53 | 53 | ||
| 54 | ST_DATA int const_wanted; /* true if constant wanted */ | 54 | ST_DATA int const_wanted; /* true if constant wanted */ |
| 55 | ST_DATA int nocode_wanted; /* no code generation wanted */ | 55 | ST_DATA int nocode_wanted; /* no code generation wanted */ |
| 56 | #define unevalmask 0xffff /* unevaluated subexpression */ | ||
| 56 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ | 57 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ |
| 57 | #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ | 58 | #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ |
| 58 | 59 | ||
| @@ -2273,7 +2274,7 @@ static void gen_opic(int op) · 2214 unmodified lines | |||
| 2273 | case TOK_UMOD: | 2274 | case TOK_UMOD: |
| 2274 | /* if division by zero, generate explicit division */ | 2275 | /* if division by zero, generate explicit division */ |
| 2275 | if (l2 == 0) { | 2276 | if (l2 == 0) { |
| 2276 | if (const_wanted) | 2277 | if (const_wanted && !(nocode_wanted & unevalmask)) |
| 2277 | tcc_error("division by zero in constant"); | 2278 | tcc_error("division by zero in constant"); |
| 2278 | goto general_case; | 2279 | goto general_case; |
| 2279 | } | 2280 | } |
| @@ -5104,7 +5105,7 @@ ST_FUNC void unary(void) · 2824 unmodified lines | |||
| 5104 | } | 5105 | } |
| 5105 | } else if (tok == '{') { | 5106 | } else if (tok == '{') { |
| 5106 | int saved_nocode_wanted = nocode_wanted; | 5107 | int saved_nocode_wanted = nocode_wanted; |
| 5107 | if (const_wanted) | 5108 | if (const_wanted && !(nocode_wanted & unevalmask)) |
| 5108 | tcc_error("expected constant"); | 5109 | tcc_error("expected constant"); |
| 5109 | /* save all registers */ | 5110 | /* save all registers */ |
| 5110 | save_regs(0); | 5111 | save_regs(0); |
| @@ -6152,9 +6153,9 @@ ST_FUNC void gexpr(void) · 1041 unmodified lines | |||
| 6152 | static void expr_const1(void) | 6153 | static void expr_const1(void) |
| 6153 | { | 6154 | { |
| 6154 | const_wanted++; | 6155 | const_wanted++; |
| 6155 | nocode_wanted++; | 6156 | nocode_wanted += unevalmask + 1; |
| 6156 | expr_cond(); | 6157 | expr_cond(); |
| 6157 | nocode_wanted--; | 6158 | nocode_wanted -= unevalmask + 1; |
| 6158 | const_wanted--; | 6159 | const_wanted--; |
| 6159 | } | 6160 | } |
| 6160 | 6161 | ||
| @@ -950,6 +950,8 @@ void expr2_test() · 949 unmodified lines | |||
| 950 | printf("res= %d %d\n", a, b); | 950 | printf("res= %d %d\n", a, b); |
| 951 | } | 951 | } |
| 952 | 952 | ||
| 953 | int const_len_ar[sizeof(1/0)]; /* div-by-zero, but in unevaluated context */ | ||
| 954 | |||
| 953 | void constant_expr_test() | 955 | void constant_expr_test() |
| 954 | { | 956 | { |
| 955 | int a; | 957 | int a; |
| @@ -958,6 +960,7 @@ void constant_expr_test() · 2 unmodified lines | |||
| 958 | printf("%d\n", a * 16); | 960 | printf("%d\n", a * 16); |
| 959 | printf("%d\n", a * 1); | 961 | printf("%d\n", a * 1); |
| 960 | printf("%d\n", a + 0); | 962 | printf("%d\n", a + 0); |
| 963 | printf("%d\n", sizeof(const_len_ar)); | ||
| 961 | } | 964 | } |
| 962 | 965 | ||
| 963 | int tab4[10]; | 966 | int tab4[10]; |
| @@ -1845,6 +1848,8 @@ arrtype2 sinit22 = {5,6,7}; · 881 unmodified lines | |||
| 1845 | int sinit23[2] = { "astring" ? sizeof("astring") : -1, | 1848 | int sinit23[2] = { "astring" ? sizeof("astring") : -1, |
| 1846 | &sinit23 ? 42 : -1 }; | 1849 | &sinit23 ? 42 : -1 }; |
| 1847 | 1850 | ||
| 1851 | int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */ | ||
| 1852 | |||
| 1848 | extern int external_inited = 42; | 1853 | extern int external_inited = 42; |
| 1849 | 1854 | ||
| 1850 | void init_test(void) | 1855 | void init_test(void) |
| @@ -1959,6 +1964,7 @@ void init_test(void) · 108 unmodified lines | |||
| 1959 | printf("arrtype6: %d\n", sizeof(arrtype2)); | 1964 | printf("arrtype6: %d\n", sizeof(arrtype2)); |
| 1960 | 1965 | ||
| 1961 | printf("sinit23= %d %d\n", sinit23[0], sinit23[1]); | 1966 | printf("sinit23= %d %d\n", sinit23[0], sinit23[1]); |
| 1967 | printf("sinit24=%d\n", sinit24); | ||
| 1962 | printf("linit18= %d %d\n", linit18[0], linit18[1]); | 1968 | printf("linit18= %d %d\n", linit18[0], linit18[1]); |
| 1963 | } | 1969 | } |
| 1964 | 1970 | ||
| @@ -151,6 +151,10 @@ int ga = 0.42 { 2 }; · 150 unmodified lines | |||
| 151 | struct S { int a, b; }; | 151 | struct S { int a, b; }; |
| 152 | struct T { struct S x; }; | 152 | struct T { struct S x; }; |
| 153 | struct T gt = { 42 a: 1, 43 }; | 153 | struct T gt = { 42 a: 1, 43 }; |
| 154 | #elif defined test_invalid_4 | ||
| 155 | enum E { | ||
| 156 | x = 1 / 0 | ||
| 157 | }; | ||
| 154 | #elif defined test_conflicting_types | 158 | #elif defined test_conflicting_types |
| 155 | int i; | 159 | int i; |
| 156 | void foo(void) { | 160 | void foo(void) { |
| @@ -72,37 +72,40 @@ · 71 unmodified lines | |||
| 72 | [test_invalid_3] | 72 | [test_invalid_3] |
| 73 | 60_errors_and_warnings.c:153: error: ',' expected (got "a") | 73 | 60_errors_and_warnings.c:153: error: ',' expected (got "a") |
| 74 | 74 | ||
| 75 | [test_invalid_4] | ||
| 76 | 60_errors_and_warnings.c:157: error: division by zero in constant | ||
| 77 | |||
| 75 | [test_conflicting_types] | 78 | [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' |
| 77 | 80 | ||
| 78 | [test_nested_types] | 81 | [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 |
| 80 | 83 | ||
| 81 | [test_vla_1] | 84 | [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 |
| 83 | 86 | ||
| 84 | [test_invalid_alignas] | 87 | [test_invalid_alignas] |
| 85 | 60_errors_and_warnings.c:177: error: identifier expected | 88 | 60_errors_and_warnings.c:181: error: identifier expected |
| 86 | 89 | ||
| 87 | [test_static_assert] | 90 | [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" |
| 89 | 92 | ||
| 90 | [test_void_array] | 93 | [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 |
| 92 | 95 | ||
| 93 | [test_incomplete_enum_array] | 96 | [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 |
| 95 | 98 | ||
| 96 | [test_incomplete_struct_array] | 99 | [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 |
| 98 | 101 | ||
| 99 | [test_const_fun_array] | 102 | [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 |
| 101 | 104 | ||
| 102 | [test_incomplete_array_array] | 105 | [test_incomplete_array_array] |
| 103 | 106 | ||
| 104 | [test_extern_array] | 107 | [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' |
| 106 | 109 | ||
| 107 | [test_func_1] | 110 | [test_func_1] |
| 108 | hello: a = 123 | 111 | hello: a = 123 |
| @@ -111,17 +114,17 @@ hello: a = 123 · 2 unmodified lines | |||
| 111 | hello: a = 123 | 114 | hello: a = 123 |
| 112 | 115 | ||
| 113 | [test_func_3] | 116 | [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' |
| 115 | hello: a = 123 | 118 | hello: a = 123 |
| 116 | 119 | ||
| 117 | [test_func_4] | 120 | [test_func_4] |
| 118 | hello: a = 123 | 121 | hello: a = 123 |
| 119 | 122 | ||
| 120 | [test_func_5] | 123 | [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' |
| 122 | 125 | ||
| 123 | [test_func_6] | 126 | [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 |
| 125 | 128 | ||
| 126 | [test_var_1] | 129 | [test_var_1] |
| 127 | main : 1 ; 1 | 130 | main : 1 ; 1 |
| @@ -134,6 +137,6 @@ main : 2 ; 2 · 6 unmodified lines | |||
| 134 | bar : 3 ; 3 | 137 | bar : 3 ; 3 |
| 135 | 138 | ||
| 136 | [test_var_3] | 139 | [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' |
| 138 | 141 | ||
| 139 | [test_var_4] | 142 | [test_var_4] |