From 4a70b2bc2d080baa4082d9d902f9172f88021019 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Wed, 15 Jan 2020 23:32:40 +0100 Subject: [PATCH] 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. --- tccgen.c | 9 +++++---- tests/tcctest.c | 6 ++++++ tests/tests2/60_errors_and_warnings.c | 4 ++++ tests/tests2/60_errors_and_warnings.expect | 31 ++++++++++++++++-------------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/tccgen.c b/tccgen.c index 990012c6..946a9e21 100644 --- a/tccgen.c +++ b/tccgen.c @@ -53,6 +53,7 @@ static SValue _vstack[1 + VSTACK_SIZE]; ST_DATA int const_wanted; /* true if constant wanted */ ST_DATA int nocode_wanted; /* no code generation wanted */ +#define unevalmask 0xffff /* unevaluated subexpression */ #define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */ #define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */ @@ -2273,7 +2274,7 @@ static void gen_opic(int op) case TOK_UMOD: /* if division by zero, generate explicit division */ if (l2 == 0) { - if (const_wanted) + if (const_wanted && !(nocode_wanted & unevalmask)) tcc_error("division by zero in constant"); goto general_case; } @@ -5104,7 +5105,7 @@ ST_FUNC void unary(void) } } else if (tok == '{') { int saved_nocode_wanted = nocode_wanted; - if (const_wanted) + if (const_wanted && !(nocode_wanted & unevalmask)) tcc_error("expected constant"); /* save all registers */ save_regs(0); @@ -6152,9 +6153,9 @@ ST_FUNC void gexpr(void) static void expr_const1(void) { const_wanted++; - nocode_wanted++; + nocode_wanted += unevalmask + 1; expr_cond(); - nocode_wanted--; + nocode_wanted -= unevalmask + 1; const_wanted--; } diff --git a/tests/tcctest.c b/tests/tcctest.c index 374ecc2c..4bf5d598 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -950,6 +950,8 @@ void expr2_test() printf("res= %d %d\n", a, b); } +int const_len_ar[sizeof(1/0)]; /* div-by-zero, but in unevaluated context */ + void constant_expr_test() { int a; @@ -958,6 +960,7 @@ void constant_expr_test() printf("%d\n", a * 16); printf("%d\n", a * 1); printf("%d\n", a + 0); + printf("%d\n", sizeof(const_len_ar)); } int tab4[10]; @@ -1845,6 +1848,8 @@ arrtype2 sinit22 = {5,6,7}; int sinit23[2] = { "astring" ? sizeof("astring") : -1, &sinit23 ? 42 : -1 }; +int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */ + extern int external_inited = 42; void init_test(void) @@ -1959,6 +1964,7 @@ void init_test(void) printf("arrtype6: %d\n", sizeof(arrtype2)); printf("sinit23= %d %d\n", sinit23[0], sinit23[1]); + printf("sinit24=%d\n", sinit24); printf("linit18= %d %d\n", linit18[0], linit18[1]); } diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index 8bc2e5e2..5a26ec6d 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -151,6 +151,10 @@ int ga = 0.42 { 2 }; struct S { int a, b; }; struct T { struct S x; }; struct T gt = { 42 a: 1, 43 }; +#elif defined test_invalid_4 +enum E { + x = 1 / 0 +}; #elif defined test_conflicting_types int i; void foo(void) { diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index e8bf251d..4c86c189 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -72,37 +72,40 @@ [test_invalid_3] 60_errors_and_warnings.c:153: error: ',' expected (got "a") +[test_invalid_4] +60_errors_and_warnings.c:157: error: division by zero in constant + [test_conflicting_types] -60_errors_and_warnings.c:159: error: incompatible types for redefinition of 'i' +60_errors_and_warnings.c:163: error: incompatible types for redefinition of 'i' [test_nested_types] -60_errors_and_warnings.c:166: error: struct/union/enum already defined +60_errors_and_warnings.c:170: error: struct/union/enum already defined [test_vla_1] -60_errors_and_warnings.c:173: error: need explicit inner array size in VLAs +60_errors_and_warnings.c:177: error: need explicit inner array size in VLAs [test_invalid_alignas] -60_errors_and_warnings.c:177: error: identifier expected +60_errors_and_warnings.c:181: error: identifier expected [test_static_assert] -60_errors_and_warnings.c:183: error: "ONE is not 1" +60_errors_and_warnings.c:187: error: "ONE is not 1" [test_void_array] -60_errors_and_warnings.c:186: error: declaration of an array of incomplete type elements +60_errors_and_warnings.c:190: error: declaration of an array of incomplete type elements [test_incomplete_enum_array] -60_errors_and_warnings.c:189: error: declaration of an array of incomplete type elements +60_errors_and_warnings.c:193: error: declaration of an array of incomplete type elements [test_incomplete_struct_array] -60_errors_and_warnings.c:192: error: declaration of an array of incomplete type elements +60_errors_and_warnings.c:196: error: declaration of an array of incomplete type elements [test_const_fun_array] -60_errors_and_warnings.c:196: error: declaration of an array of functions +60_errors_and_warnings.c:200: error: declaration of an array of functions [test_incomplete_array_array] [test_extern_array] -60_errors_and_warnings.c:212: error: incompatible types for redefinition of 'x' +60_errors_and_warnings.c:216: error: incompatible types for redefinition of 'x' [test_func_1] hello: a = 123 @@ -111,17 +114,17 @@ hello: a = 123 hello: a = 123 [test_func_3] -60_errors_and_warnings.c:242: warning: static storage ignored for redefinition of 'hello' +60_errors_and_warnings.c:246: warning: static storage ignored for redefinition of 'hello' hello: a = 123 [test_func_4] hello: a = 123 [test_func_5] -60_errors_and_warnings.c:242: error: incompatible types for redefinition of 'hello' +60_errors_and_warnings.c:246: error: incompatible types for redefinition of 'hello' [test_func_6] -60_errors_and_warnings.c:230: error: function without file scope cannot be static +60_errors_and_warnings.c:234: error: function without file scope cannot be static [test_var_1] main : 1 ; 1 @@ -134,6 +137,6 @@ main : 2 ; 2 bar : 3 ; 3 [test_var_3] -60_errors_and_warnings.c:274: error: incompatible types for redefinition of 'xxx' +60_errors_and_warnings.c:278: error: incompatible types for redefinition of 'xxx' [test_var_4] -- 2.11.4.GIT