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.
This commit is contained in:
Michael Matz 2020-01-15 23:32:40 +01:00
parent 3877618785
commit 4a70b2bc2d
4 changed files with 32 additions and 18 deletions

View File

@ -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--;
}

View File

@ -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]);
}

View File

@ -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) {

View File

@ -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]