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 | 54 | ST_DATA int const_wanted; /* true if constant wanted */ |
| 55 | 55 | ST_DATA int nocode_wanted; /* no code generation wanted */ |
| 56 | +#define unevalmask 0xffff /* unevaluated subexpression */ | |
| 56 | 57 | #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ |
| 57 | 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 | 2274 | case TOK_UMOD: |
| 2274 | 2275 | /* if division by zero, generate explicit division */ |
| 2275 | 2276 | if (l2 == 0) { |
| 2276 | − if (const_wanted) | |
| 2277 | + if (const_wanted && !(nocode_wanted & unevalmask)) | |
| 2277 | 2278 | tcc_error("division by zero in constant"); |
| 2278 | 2279 | goto general_case; |
| 2279 | 2280 | } |
| @@ -5104,7 +5105,7 @@ ST_FUNC void unary(void) · 2824 unmodified lines | ||
| 5104 | 5105 | } |
| 5105 | 5106 | } else if (tok == '{') { |
| 5106 | 5107 | int saved_nocode_wanted = nocode_wanted; |
| 5107 | − if (const_wanted) | |
| 5108 | + if (const_wanted && !(nocode_wanted & unevalmask)) | |
| 5108 | 5109 | tcc_error("expected constant"); |
| 5109 | 5110 | /* save all registers */ |
| 5110 | 5111 | save_regs(0); |
| @@ -6152,9 +6153,9 @@ ST_FUNC void gexpr(void) · 1041 unmodified lines | ||
| 6152 | 6153 | static void expr_const1(void) |
| 6153 | 6154 | { |
| 6154 | 6155 | const_wanted++; |
| 6155 | − nocode_wanted++; | |
| 6156 | + nocode_wanted += unevalmask + 1; | |
| 6156 | 6157 | expr_cond(); |
| 6157 | − nocode_wanted--; | |
| 6158 | + nocode_wanted -= unevalmask + 1; | |
| 6158 | 6159 | const_wanted--; |
| 6159 | 6160 | } |
| 6160 | 6161 | |
| @@ -950,6 +950,8 @@ void expr2_test() · 949 unmodified lines | ||
| 950 | 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 | 955 | void constant_expr_test() |
| 954 | 956 | { |
| 955 | 957 | int a; |
| @@ -958,6 +960,7 @@ void constant_expr_test() · 2 unmodified lines | ||
| 958 | 960 | printf("%d\n", a * 16); |
| 959 | 961 | printf("%d\n", a * 1); |
| 960 | 962 | printf("%d\n", a + 0); |
| 963 | + printf("%d\n", sizeof(const_len_ar)); | |
| 961 | 964 | } |
| 962 | 965 | |
| 963 | 966 | int tab4[10]; |
| @@ -1845,6 +1848,8 @@ arrtype2 sinit22 = {5,6,7}; · 881 unmodified lines | ||
| 1845 | 1848 | int sinit23[2] = { "astring" ? sizeof("astring") : -1, |
| 1846 | 1849 | &sinit23 ? 42 : -1 }; |
| 1847 | 1850 | |
| 1851 | +int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */ | |
| 1852 | + | |
| 1848 | 1853 | extern int external_inited = 42; |
| 1849 | 1854 | |
| 1850 | 1855 | void init_test(void) |
| @@ -1959,6 +1964,7 @@ void init_test(void) · 108 unmodified lines | ||
| 1959 | 1964 | printf("arrtype6: %d\n", sizeof(arrtype2)); |
| 1960 | 1965 | |
| 1961 | 1966 | printf("sinit23= %d %d\n", sinit23[0], sinit23[1]); |
| 1967 | + printf("sinit24=%d\n", sinit24); | |
| 1962 | 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 | 151 | struct S { int a, b; }; |
| 152 | 152 | struct T { struct S x; }; |
| 153 | 153 | struct T gt = { 42 a: 1, 43 }; |
| 154 | +#elif defined test_invalid_4 | |
| 155 | +enum E { | |
| 156 | + x = 1 / 0 | |
| 157 | +}; | |
| 154 | 158 | #elif defined test_conflicting_types |
| 155 | 159 | int i; |
| 156 | 160 | void foo(void) { |
| @@ -72,37 +72,40 @@ · 71 unmodified lines | ||
| 72 | 72 | [test_invalid_3] |
| 73 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 105 | [test_incomplete_array_array] |
| 103 | 106 | |
| 104 | 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 | 110 | [test_func_1] |
| 108 | 111 | hello: a = 123 |
| @@ -111,17 +114,17 @@ hello: a = 123 · 2 unmodified lines | ||
| 111 | 114 | hello: a = 123 |
| 112 | 115 | |
| 113 | 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 | 118 | hello: a = 123 |
| 116 | 119 | |
| 117 | 120 | [test_func_4] |
| 118 | 121 | hello: a = 123 |
| 119 | 122 | |
| 120 | 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 | 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 | 129 | [test_var_1] |
| 127 | 130 | main : 1 ; 1 |
| @@ -134,6 +137,6 @@ main : 2 ; 2 · 6 unmodified lines | ||
| 134 | 137 | bar : 3 ; 3 |
| 135 | 138 | |
| 136 | 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 | 142 | [test_var_4] |