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:
parent
3877618785
commit
4a70b2bc2d
4 changed files with 32 additions and 18 deletions
9
tccgen.c
9
tccgen.c
|
|
@ -53,6 +53,7 @@ static SValue _vstack[1 + VSTACK_SIZE];
|
||||||
|
|
||||||
ST_DATA int const_wanted; /* true if constant wanted */
|
ST_DATA int const_wanted; /* true if constant wanted */
|
||||||
ST_DATA int nocode_wanted; /* no code generation 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 NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
|
||||||
#define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */
|
#define STATIC_DATA_WANTED (nocode_wanted & 0xC0000000) /* only static data output */
|
||||||
|
|
||||||
|
|
@ -2273,7 +2274,7 @@ static void gen_opic(int op)
|
||||||
case TOK_UMOD:
|
case TOK_UMOD:
|
||||||
/* if division by zero, generate explicit division */
|
/* if division by zero, generate explicit division */
|
||||||
if (l2 == 0) {
|
if (l2 == 0) {
|
||||||
if (const_wanted)
|
if (const_wanted && !(nocode_wanted & unevalmask))
|
||||||
tcc_error("division by zero in constant");
|
tcc_error("division by zero in constant");
|
||||||
goto general_case;
|
goto general_case;
|
||||||
}
|
}
|
||||||
|
|
@ -5104,7 +5105,7 @@ ST_FUNC void unary(void)
|
||||||
}
|
}
|
||||||
} else if (tok == '{') {
|
} else if (tok == '{') {
|
||||||
int saved_nocode_wanted = nocode_wanted;
|
int saved_nocode_wanted = nocode_wanted;
|
||||||
if (const_wanted)
|
if (const_wanted && !(nocode_wanted & unevalmask))
|
||||||
tcc_error("expected constant");
|
tcc_error("expected constant");
|
||||||
/* save all registers */
|
/* save all registers */
|
||||||
save_regs(0);
|
save_regs(0);
|
||||||
|
|
@ -6152,9 +6153,9 @@ ST_FUNC void gexpr(void)
|
||||||
static void expr_const1(void)
|
static void expr_const1(void)
|
||||||
{
|
{
|
||||||
const_wanted++;
|
const_wanted++;
|
||||||
nocode_wanted++;
|
nocode_wanted += unevalmask + 1;
|
||||||
expr_cond();
|
expr_cond();
|
||||||
nocode_wanted--;
|
nocode_wanted -= unevalmask + 1;
|
||||||
const_wanted--;
|
const_wanted--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -950,6 +950,8 @@ void expr2_test()
|
||||||
printf("res= %d %d\n", a, b);
|
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()
|
void constant_expr_test()
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
|
|
@ -958,6 +960,7 @@ void constant_expr_test()
|
||||||
printf("%d\n", a * 16);
|
printf("%d\n", a * 16);
|
||||||
printf("%d\n", a * 1);
|
printf("%d\n", a * 1);
|
||||||
printf("%d\n", a + 0);
|
printf("%d\n", a + 0);
|
||||||
|
printf("%d\n", sizeof(const_len_ar));
|
||||||
}
|
}
|
||||||
|
|
||||||
int tab4[10];
|
int tab4[10];
|
||||||
|
|
@ -1845,6 +1848,8 @@ arrtype2 sinit22 = {5,6,7};
|
||||||
int sinit23[2] = { "astring" ? sizeof("astring") : -1,
|
int sinit23[2] = { "astring" ? sizeof("astring") : -1,
|
||||||
&sinit23 ? 42 : -1 };
|
&sinit23 ? 42 : -1 };
|
||||||
|
|
||||||
|
int sinit24 = 2 || 1 / 0; /* exception in constant but unevaluated context */
|
||||||
|
|
||||||
extern int external_inited = 42;
|
extern int external_inited = 42;
|
||||||
|
|
||||||
void init_test(void)
|
void init_test(void)
|
||||||
|
|
@ -1959,6 +1964,7 @@ void init_test(void)
|
||||||
printf("arrtype6: %d\n", sizeof(arrtype2));
|
printf("arrtype6: %d\n", sizeof(arrtype2));
|
||||||
|
|
||||||
printf("sinit23= %d %d\n", sinit23[0], sinit23[1]);
|
printf("sinit23= %d %d\n", sinit23[0], sinit23[1]);
|
||||||
|
printf("sinit24=%d\n", sinit24);
|
||||||
printf("linit18= %d %d\n", linit18[0], linit18[1]);
|
printf("linit18= %d %d\n", linit18[0], linit18[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,10 @@ int ga = 0.42 { 2 };
|
||||||
struct S { int a, b; };
|
struct S { int a, b; };
|
||||||
struct T { struct S x; };
|
struct T { struct S x; };
|
||||||
struct T gt = { 42 a: 1, 43 };
|
struct T gt = { 42 a: 1, 43 };
|
||||||
|
#elif defined test_invalid_4
|
||||||
|
enum E {
|
||||||
|
x = 1 / 0
|
||||||
|
};
|
||||||
#elif defined test_conflicting_types
|
#elif defined test_conflicting_types
|
||||||
int i;
|
int i;
|
||||||
void foo(void) {
|
void foo(void) {
|
||||||
|
|
|
||||||
|
|
@ -72,37 +72,40 @@
|
||||||
[test_invalid_3]
|
[test_invalid_3]
|
||||||
60_errors_and_warnings.c:153: error: ',' expected (got "a")
|
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]
|
[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]
|
[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]
|
[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]
|
[test_invalid_alignas]
|
||||||
60_errors_and_warnings.c:177: error: identifier expected
|
60_errors_and_warnings.c:181: error: identifier expected
|
||||||
|
|
||||||
[test_static_assert]
|
[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]
|
[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]
|
[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]
|
[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]
|
[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_incomplete_array_array]
|
||||||
|
|
||||||
[test_extern_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]
|
[test_func_1]
|
||||||
hello: a = 123
|
hello: a = 123
|
||||||
|
|
@ -111,17 +114,17 @@ hello: a = 123
|
||||||
hello: a = 123
|
hello: a = 123
|
||||||
|
|
||||||
[test_func_3]
|
[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
|
hello: a = 123
|
||||||
|
|
||||||
[test_func_4]
|
[test_func_4]
|
||||||
hello: a = 123
|
hello: a = 123
|
||||||
|
|
||||||
[test_func_5]
|
[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]
|
[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]
|
[test_var_1]
|
||||||
main : 1 ; 1
|
main : 1 ; 1
|
||||||
|
|
@ -134,6 +137,6 @@ main : 2 ; 2
|
||||||
bar : 3 ; 3
|
bar : 3 ; 3
|
||||||
|
|
||||||
[test_var_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]
|
[test_var_4]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue