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.
Unified · Split
| @@ -995,7 +995,9 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) · 994 unmodified lines | |||
| 995 | { | 995 | { |
| 996 | Sym *s; | 996 | Sym *s; |
| 997 | s = sym_find(v); | 997 | s = sym_find(v); |
| 998 | if (!s) { | 998 | if (!s || (!(s->type.t & VT_EXTERN) && (s->type.t & VT_BTYPE) != VT_FUNC)) { |
| 999 | if (s && !is_compatible_types(&s->type, type)) | ||
| 1000 | tcc_error("conflicting types for '%s'", get_tok_str(s->v, NULL)); | ||
| 999 | /* push forward reference */ | 1001 | /* push forward reference */ |
| 1000 | s = sym_push(v, type, r | VT_CONST | VT_SYM, 0); | 1002 | s = sym_push(v, type, r | VT_CONST | VT_SYM, 0); |
| 1001 | s->type.t |= VT_EXTERN; | 1003 | s->type.t |= VT_EXTERN; |
| @@ -77,6 +77,7 @@ void expr_test(); · 76 unmodified lines | |||
| 77 | void macro_test(); | 77 | void macro_test(); |
| 78 | void recursive_macro_test(); | 78 | void recursive_macro_test(); |
| 79 | void scope_test(); | 79 | void scope_test(); |
| 80 | void scope_test2(); | ||
| 80 | void forward_test(); | 81 | void forward_test(); |
| 81 | void funcptr_test(); | 82 | void funcptr_test(); |
| 82 | void loop_test(); | 83 | void loop_test(); |
| @@ -718,6 +719,7 @@ int main(int argc, char **argv) · 635 unmodified lines | |||
| 718 | macro_test(); | 719 | macro_test(); |
| 719 | recursive_macro_test(); | 720 | recursive_macro_test(); |
| 720 | scope_test(); | 721 | scope_test(); |
| 722 | scope_test2(); | ||
| 721 | forward_test(); | 723 | forward_test(); |
| 722 | funcptr_test(); | 724 | funcptr_test(); |
| 723 | loop_test(); | 725 | loop_test(); |
| @@ -800,6 +802,20 @@ void scope_test() · 76 unmodified lines | |||
| 800 | printf("g5=%d\n", g); | 802 | printf("g5=%d\n", g); |
| 801 | } | 803 | } |
| 802 | 804 | ||
| 805 | int st2_i; | ||
| 806 | int *st2_p = &st2_i; | ||
| 807 | void scope_test2() | ||
| 808 | { | ||
| 809 | char a[50]; | ||
| 810 | st2_i = 42; | ||
| 811 | for (int st2_i = 1; st2_i < 10; st2_i++) { | ||
| 812 | extern int st2_i; | ||
| 813 | st2_i++; | ||
| 814 | printf("exloc: %d\n", st2_i); | ||
| 815 | } | ||
| 816 | printf("exloc: %d\n", *st2_p); | ||
| 817 | } | ||
| 818 | |||
| 803 | void array_test() | 819 | void array_test() |
| 804 | { | 820 | { |
| 805 | int i, j, a[4]; | 821 | int i, j, a[4]; |
| @@ -151,4 +151,13 @@ int ga = 0.42 { 2 }; · 150 unmodified lines | |||
| 151 | struct S { int a, b; }; | 151 | struct S { int a, b; }; |
| 152 | struct T { struct S x; }; | 152 | struct T { struct S x; }; |
| 153 | struct T gt = { 42 a: 1, 43 }; | 153 | struct T gt = { 42 a: 1, 43 }; |
| 154 | #elif defined test_conflicting_types | ||
| 155 | int i; | ||
| 156 | void foo(void) { | ||
| 157 | int i; | ||
| 158 | { | ||
| 159 | extern double i; | ||
| 160 | i = 42.2; | ||
| 161 | } | ||
| 162 | } | ||
| 154 | #endif | 163 | #endif |
| @@ -71,3 +71,6 @@ · 70 unmodified lines | |||
| 71 | 71 | ||
| 72 | [test_invalid_3] | 72 | [test_invalid_3] |
| 73 | 60_errors_and_warnings.c:153: error: ',' expected (got "a") | 73 | 60_errors_and_warnings.c:153: error: ',' expected (got "a") |
| 74 | |||
| 75 | [test_conflicting_types] | ||
| 76 | 60_errors_and_warnings.c:159: error: conflicting types for 'i' | ||