From 355897a9203661b5f54dbb634294a66ceef17ae6 Mon Sep 17 00:00:00 2001
From: Arthur Williams <taaparthur@gmail.com>
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 <stdio.h>
 
+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'