Am Donnerstag, dem 23.01.2025 um 17:39 +0000 schrieb Qing Zhao:
> 
> > On Jan 22, 2025, at 12:20, Martin Uecker <uec...@tugraz.at> wrote:
> > 
> > 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;
> > }
> > 
> > 
> In this workaround, we also need to introduce a new key word “__self__”,  
> Is this the same as the “__self__” Joseph mentioned in a previous email 
> (I copied Joseph’s word in below for easy reference):

I think it could be same, although Joseph uses it with a member access.  

One could also use designator syntax (without __self__) and pass a reference
to the member only (which also seems appropriate for counted_by).

struct foo {
 int z;
 float f;
}

size_t bar_count(struct foo (*yp)[5][10]);

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

size_t bar_count(struct foo (*yp)[5][10])
{
 return (*yp)[1][3].z +4;
}


I still prefer the version without __self__ and will respond to Michael
why I think so,  but I am also fine *with* __self__.  I just think the
delayed parsing version used in the Apple prototype should be avoided,
because it is very confusing (and  because it needs delayed parsing).


> 
> 
> "But if you want a less-limited feature that allows for expressions, you 
> need some syntax for referring to a structure member that's not ambiguous.  
> For example, some new notation such as __self__.len1 to refer to a member 
> of the closest enclosing structure definition when in counted_by (while 
> being invalid except in counted_by inside a structure definition).  
> (That's just one example of how you might define syntax that avoids 
> ambiguity.)”
> 
> So, for the following two approaches to represent expression as argument of 
> “counted_by” attribute:
> 
> A.  Allowing  function call as the argument, and the new key word “__self__” 
> is passed to this function to
> reference members of the closest enclosing structure.
> 
> > struct bar {
> >  char *array __attribute__ ((counted_by (bar_count(__self__))));
> >  struct foo y[5][10];
> > }
> 
> 
> B. Allowing expression with __self__ as the argument:
> 
> > struct bar {
> >  char *array __attribute__ ((counted_by (__self__.y[1][3].z + 4)));
> >  struct foo y[5][10];
> > }
> 
> 
> My question:
> 
> Which is better, A or B? 

B does not work, because you can not parse the expression using the
existing parser because the type of y is unknown.

I also do not really like A because I think we should not allow function
calls, so I tend to favour the version with the cast at the moment.

Martin

> 
> 
> Thanks a lot for your help.
> 
> Qing
> 
> > 
> > > 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