From 355897a9203661b5f54dbb634294a66ceef17ae6 Mon Sep 17 00:00:00 2001 From: Arthur Williams Date: Sat, 13 Feb 2021 18:37:25 -0800 Subject: [PATCH] Allow declared arrays to be initialized without an explicit size When defining an array with non-explicit size, one would get "incompatible types for redefinition of 'array' if the array was already declared with a different size. For example: extern int array[2]; int array[] = {1}; would fail to compile with tcc. Instead the above is now equivalent to: int array[] = {1, 0}; --- tccgen.c | 12 ++++++++++++ tests/tests2/36_array_initialisers.c | 4 ++++ tests/tests2/36_array_initialisers.expect | 10 ++++++++++ tests/tests2/60_errors_and_warnings.c | 5 +++++ tests/tests2/60_errors_and_warnings.expect | 3 +++ 5 files changed, 34 insertions(+) diff --git a/tccgen.c b/tccgen.c index aa15831a..bad46590 100644 --- a/tccgen.c +++ b/tccgen.c @@ -8437,6 +8437,18 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* prepare second initializer parsing */ macro_ptr = init_str->str; next(); + + sym = sym_find(v); + /* If the base type itself was an array type of unspecified size + (like in 'int arr[] = {1};') when the array was already declared + (like in 'extern arr[10];') we want to use the originally declared + size and not deduce it from the initializer */ + if(sym && sym->type.ref->c > 0) { + if(type->ref->c > sym->type.ref->c) + tcc_error("incompatible types for redefinition of '%s'", + get_tok_str(sym->v, NULL)); + type->ref->c = sym->type.ref->c; + } /* if still unknown size, error */ size = type_size(type, &align); diff --git a/tests/tests2/36_array_initialisers.c b/tests/tests2/36_array_initialisers.c index 1bc8ee08..ac56f5ad 100644 --- a/tests/tests2/36_array_initialisers.c +++ b/tests/tests2/36_array_initialisers.c @@ -1,5 +1,7 @@ #include +extern int Array3[10]; +int Array3[] = { 12, 34, }; int main() { int Count; @@ -14,6 +16,8 @@ int main() for (Count = 0; Count < 10; Count++) printf("%d: %d\n", Count, Array2[Count]); + for (Count = 0; Count < 10; Count++) + printf("%d: %d\n", Count, Array3[Count]); return 0; } diff --git a/tests/tests2/36_array_initialisers.expect b/tests/tests2/36_array_initialisers.expect index 3ac6c772..4bb5ab7c 100644 --- a/tests/tests2/36_array_initialisers.expect +++ b/tests/tests2/36_array_initialisers.expect @@ -18,3 +18,13 @@ 7: 789 8: 8642 9: 9753 +0: 12 +1: 34 +2: 0 +3: 0 +4: 0 +5: 0 +6: 0 +7: 0 +8: 0 +9: 0 diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index 363469d5..5c576061 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -383,4 +383,9 @@ struct S2 { int d; }; }; + +/******************************************************************/ +#elif defined test_conflicting_array_definition +extern int array[2]; +int array[] = { 1, 2, 3 }; #endif diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index fee50c42..ad3c3808 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -180,3 +180,6 @@ bar : 3 ; 3 [test_duplicate_member_anon] 60_errors_and_warnings.c:385: error: duplicate member 'd' + +[test_conflicting_array_definition] +60_errors_and_warnings.c:390: error: incompatible types for redefinition of 'array'