Am Dienstag, dem 18.03.2025 um 09:52 -0700 schrieb Yeoul Na via Gcc:
> 
> > On Mar 18, 2025, at 12:16 AM, Martin Uecker <uec...@tugraz.at> wrote:
> > 
> > When xp->ptr is accessed, the size expression
> > is evaluated and the lvalue which is formed at this point in
> > time gets the type int(*)[xp->count], similar to how the size
> > expression of function arguments are evaluated when the
> > function is entered. The type of this expression
> > then does not change anymore. You could implement it
> > by rewriting it to the following.
> 
> Yes, that’s effectively similar to how the size of bounds annotations work 
> too.
> 
> Though my question was, VLA types currently don't work this way.
> 
> The size is evaluated when it’s declared as you all discussed earlier.
this is the case only for automatic variables.  For function arguments
they are evaluated at function entry.

> So do you mean you want to fix the current behavior or make the

I think the current behavior is fine, and changing it
would also be problematic for existing code.

> behavior inconsistent between if they are struct members,
> indirect pointers vs. local variables like below? 

I think the nature of the problem requires that the size
expression must be evaluated at different time points
depending on the scenario.

For automatic variables, this is when the declaration is
reached in the control flow and for function arguments when
the function is entered.  For structure members where the size
expression refers to other members, they need to be
evaluated when the member is accessed. 

> 
> void test(struct X *xp) {
>     int len = 10;
>     int (*ptr)[len] = malloc(sizeof(int) * len); // (1) int (*ptr)[len] is 
> evaluated here and fixed.  
> 
>     xp->count = 100;
>     xp->ptr = malloc(sizeof(int) * 100); // size of xp->ptr is dynamically 
> evaluated with xp->count, hence, this works fine.
> 
>     len = 5; // (2)
>     ptr = malloc(sizeof(int) * len); // size of ptr is still fixed to be (1), 
> so this traps at run time. 
> }

Yes.

For GNU C (but not ISO C) there could be size expression in
the declaration referring to automatic variables.

int foo()
{
  int n = 1;
  struct {
   char buf[n]; // evaluated when the declaration is reached
  } x;
};

This is something which can not currently happen for ISO C where
this can only refer to named constants and where the size is
evaluated at compile time.

int foo()
{
  enum { N = 1 };
  struct {
    char buf[N];
  } x;
}

Still, I think this is another reason why it would be much
better to have new syntax for this.  We also need to restrict
the size expressions in all three scenarios in different ways.

int foo()
{ 
  int n = 1;
  struct {

    int m;
    char buf1[n];       // evaluated when the declaration is reached
    char buf2[.m];      // evaluated on access to buf2, restricted syntax
  } x { .m = 10 };
}


Martin



Reply via email to