Fix local extern vardecl
see testcases. A local 'extern int i' declaration needs to refer to the global declaration, not to a local one it might be shadowing. Doesn't seem to happen in the wild very often as this was broken forever.
This commit is contained in:
parent
e6980f6cc7
commit
1fd3709379
4 changed files with 31 additions and 1 deletions
4
tccgen.c
4
tccgen.c
|
@ -995,7 +995,9 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
|
||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
s = sym_find(v);
|
s = sym_find(v);
|
||||||
if (!s) {
|
if (!s || (!(s->type.t & VT_EXTERN) && (s->type.t & VT_BTYPE) != VT_FUNC)) {
|
||||||
|
if (s && !is_compatible_types(&s->type, type))
|
||||||
|
tcc_error("conflicting types for '%s'", get_tok_str(s->v, NULL));
|
||||||
/* push forward reference */
|
/* push forward reference */
|
||||||
s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
|
s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
|
||||||
s->type.t |= VT_EXTERN;
|
s->type.t |= VT_EXTERN;
|
||||||
|
|
|
@ -77,6 +77,7 @@ void expr_test();
|
||||||
void macro_test();
|
void macro_test();
|
||||||
void recursive_macro_test();
|
void recursive_macro_test();
|
||||||
void scope_test();
|
void scope_test();
|
||||||
|
void scope_test2();
|
||||||
void forward_test();
|
void forward_test();
|
||||||
void funcptr_test();
|
void funcptr_test();
|
||||||
void loop_test();
|
void loop_test();
|
||||||
|
@ -718,6 +719,7 @@ int main(int argc, char **argv)
|
||||||
macro_test();
|
macro_test();
|
||||||
recursive_macro_test();
|
recursive_macro_test();
|
||||||
scope_test();
|
scope_test();
|
||||||
|
scope_test2();
|
||||||
forward_test();
|
forward_test();
|
||||||
funcptr_test();
|
funcptr_test();
|
||||||
loop_test();
|
loop_test();
|
||||||
|
@ -800,6 +802,20 @@ void scope_test()
|
||||||
printf("g5=%d\n", g);
|
printf("g5=%d\n", g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int st2_i;
|
||||||
|
int *st2_p = &st2_i;
|
||||||
|
void scope_test2()
|
||||||
|
{
|
||||||
|
char a[50];
|
||||||
|
st2_i = 42;
|
||||||
|
for (int st2_i = 1; st2_i < 10; st2_i++) {
|
||||||
|
extern int st2_i;
|
||||||
|
st2_i++;
|
||||||
|
printf("exloc: %d\n", st2_i);
|
||||||
|
}
|
||||||
|
printf("exloc: %d\n", *st2_p);
|
||||||
|
}
|
||||||
|
|
||||||
void array_test()
|
void array_test()
|
||||||
{
|
{
|
||||||
int i, j, a[4];
|
int i, j, a[4];
|
||||||
|
|
|
@ -151,4 +151,13 @@ 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_conflicting_types
|
||||||
|
int i;
|
||||||
|
void foo(void) {
|
||||||
|
int i;
|
||||||
|
{
|
||||||
|
extern double i;
|
||||||
|
i = 42.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -71,3 +71,6 @@
|
||||||
|
|
||||||
[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_conflicting_types]
|
||||||
|
60_errors_and_warnings.c:159: error: conflicting types for 'i'
|
||||||
|
|
Loading…
Reference in a new issue