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 > > > > > > > > >