windelbouwman / ppci

A compiler for ARM, X86, MSP430, xtensa and more implemented in pure Python
https://ppci.readthedocs.io/en/latest/
BSD 2-Clause "Simplified" License
337 stars 36 forks source link

pcci-cc: handling of array type of unknown size #105

Open tstreiff opened 4 years ago

tstreiff commented 4 years ago

A subtle one...

#include <stdio.h>
#include <assert.h>

typedef int A[];      // array of unknow size (incomplete type)

A a1 = { 1, 2, 3, };  // initialized array of 3 ints
A a2 = { 1, 2, };     // initialized array of 2 ints
A a3;                 // illegal: cannot determine size

int main() {
  assert((sizeof(a1) / sizeof(int)) == 3);
  assert(a1[0] == 1);
  assert(a1[1] == 2);
  assert(a1[2] == 3);

  assert((sizeof(a2) / sizeof(int)) == 2);
  assert(a2[0] == 1);
  assert(a2[1] == 2);

  printf("sizeof(a3) = %d\n", sizeof(a3));

  return 0;
}

When a1 is processed, its type is formed from the incomplete type A, completed with the size 3, deduced from its initializer. But this seems to update A type itself, so that all further declarations using A are impacted. Type A becomes a 3 ints array type.

This would explain why a2 contains 3 ints (instead of 2) and declaration of a3 is accepted (and it also contains 3 ints)

There is a similar example in the C standard in the "Initialization" section, that explains the expected behaviour:

EXAMPLE 7 One form of initialization that completes array types involves typedef names. Given the declaration typedef int A[]; // OK - declared with block scope the declaration A a = { 1, 2 }, b = { 3, 4, 5 }; is identical to int a[] = { 1, 2 }, b[] = { 3, 4, 5 }; due to the rules for incomplete types.