Op 31-07-2025 om 09:39 schreef Freelance Roemke:

Hi,

I just tried to compile a 35 year old code (not from me) that looks similar to

cat <<-KWC > kw.c
#include <stdio.h>

typedef    char    *keywords[];

extern    keywords    ord2kw;
extern    keywords    ord3kw;

keywords ord2kw= {
    "E", "L", NULL
};


keywords ord3kw= {
    "D", "T", "I",
    "D2", "T2", "I2", "P",
    "P2", "V", NULL
};


int main()
{
    printf("%u\n",sizeof ord2kw);
    printf("%u\n",sizeof ord3kw);
}
KWC

and while all the gcc and clang version since then have compiled it and also used a different size for ord2kw and ord3kw, tcc now tells me

kw.c:16: error: too many initializers

and only if both ord2kw and ord3kw have the same number of elements, the error message disappears.



Could anyone enlighten me the reason for that, maybe with a reference to the C89 or C99 standard?


As far as I read the C99 standard, e.g., it says

/6.7.8 22 If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. At the end of its initializer list, the *array* no longer
has incomplete type.
/
but IMHO this does not mean that the *type* (here keywords) no longer has an incomplete type.


And is there an option to change that behaviour?

I think I found the problem. The typedef type was used twice.
The first time ord2kw set the type to size 3.
Then ord3kw overflowed because the size was now 3.
(It also works when you remove the 2 extern lines)

So I unshared the type with attached patch.
I am not sure I did this at the rigth place but it works
for the testsuite and some other code.

    Herman
diff --git a/tccgen.c b/tccgen.c
index c25a224..d142e74 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -8211,13 +8211,21 @@ static void decl_initializer_alloc(CType *type, 
AttributeDef *ad, int r,
             /* see if the symbol was already defined */
             sym = sym_find(v);
             if (sym) {
-                if (p.flex_array_ref && (sym->type.t & type->t & VT_ARRAY)
-                    && sym->type.ref->c > type->ref->c) {
-                    /* flex array was already declared with explicit size
-                            extern int arr[10];
-                            int arr[] = { 1,2,3 }; */
-                    type->ref->c = sym->type.ref->c;
-                    size = type_size(type, &align);
+                if (p.flex_array_ref && (sym->type.t & type->t & VT_ARRAY)) {
+                    if (sym->type.ref->c > type->ref->c) {
+                       /* flex array was already declared with explicit size
+                               extern int arr[10];
+                               int arr[] = { 1,2,3 }; */
+                       type->ref->c = sym->type.ref->c;
+                       size = type_size(type, &align);
+                   }
+                   /* unshare type in case of:
+                              typedef int key[];
+                              key a; key b;
+                              key a = { 1 }; key b = { 1, 2 };
+                    */
+                   sym->type.ref = sym_push(SYM_FIELD, &sym->type.ref->type,
+                                            0, sym->type.ref->c);
                 }
                 patch_storage(sym, ad, type);
                 /* we accept several definitions of the same global variable. 
*/
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to