Am Mittwoch, dem 22.01.2025 um 18:11 +0100 schrieb Martin Uecker:
> Am Mittwoch, dem 22.01.2025 um 16:37 +0000 schrieb Qing Zhao:
> > 
> > > On Jan 22, 2025, at 11:22, Martin Uecker <uec...@tugraz.at> wrote:
> > > 
> > > 
> > > Hello Michael,
> > > 
> > > Am Mittwoch, dem 22.01.2025 um 16:54 +0100 schrieb Michael Matz:
> > > > On Wed, 22 Jan 2025, Martin Uecker wrote:
> > > > 
> > > > > > > So you do not need to look further.  But maybe I am missing 
> > > > > > > something 
> > > > > > > else.
> > > > > > 
> > > > > > Like ...
> > > > > > 
> > > > > > > > Note further that you may have '{ .y[1][3].z }', which is still 
> > > > > > > > not a 
> > > > > > > > designation, but an expression under your proposal, whereas
> > > > > > > > '{ .y[1][3].z = 1 }' would remain a designation.  This shows 
> > > > > > > > that you 
> > > > > > > > now need arbitrary look-ahead to disambiguate the two.  A Very 
> > > > > > > > Bad Idea.
> > > > > > 
> > > > > > ... this?
> > > > > 
> > > > > In .y[1][3].z  after .y you can decide whether y is a member of the
> > > > > struct being initialized.  If it is, it is a designator and if not
> > > > > it must be an expression.
> > > > 
> > > > If y is not a member it must be an expression, true.  But if it's a 
> > > > member 
> > > > you don't know, it may be a designation or an expression.
> > > 
> > > In an initializer I know all the members.
> > 
> > I am not familiar with the parser, so, I am a little confused about the 
> > following:
> > 
> > Suppose we have:
> > 
> > struct foo {
> >   int z;
> >   float f;
> > }
> > 
> > struct bar {
> >   char *array __attribute__ ((counted_by (.y[1][3].z + 4)));
> >   struct foo y[5][10];
> > }
> > 
> > So, in the above, when parsing the above expression inside counted_by, can 
> > the
> > current parser be easily to be extended to parse it?
> 
> No, I don't think this can be done easily. The issue is that you do
> not know the declaration for y because it hasn't been parsed yet. 
> 
> If you forward reference some struct member, you have several
> possibilities:
> 
> - use it only in limited contexts where you do not need to know
>   the type (e.g. this works for goto labels) or for a basic
>   counted_by attribute that only takes an identifier as we have it now.
> 
> - simply assume it has a certain type (size_t as is proposed in the 
>   WG14 paper Joseph mentioned) and fail later if it does not.
> 
> 
> Both options would rule the construct above (but there could be
> workarounds). 

One of the workarounds could be to instead call a function (which could
be inlined later) and that function takes a pointer to the member. 
Then it does not need to now anything about any member, e.g.:


struct foo {
  int z;
  float f;
}

size_t bar_count(struct bar *);

struct bar {
  char *array __attribute__ ((counted_by (bar_count(__self__))));
  struct foo y[5][10];
}

size_t bar_count(struct bar *p)
{
  return p->y[1][3].z +4;
}



>  Other alternatives are:
> 
> - you have same kind of forward declaration (as we have for
>   parameters  as GNU extension). In the context of C, this is the
>   cleanest solution but either requires forward declaring the
>   full struct (which can be done in C23) or new syntax for only
>   forward declaring the member.

A possible C23 workaround could be:

struct foo {
  int z;
  float f;
}

struct bar {
  char *array __attribute__ ((counted_by (*))); 
  // star indicates missing size exppression
  struct foo y[5][10];
}

struct bar { // redeclare with known size
  char *array __attribute__ ((counted_by (.y[1][3].z + 4)));
  struct foo y[5][10];
}


Martin


> 
> - or you use some delayed parsing where you store away the tokens
>   and parse it later when all structure members are done. I think
>   this is a highly problematic approach for a variety of reasons.
> 
> 
> Martin
> 
> 
> > 
> > thanks.
> > 
> > Qing
> > > 
> > > Martin 
> > > 
> > > 
> > 
> 

Reply via email to