On Mon, Jul 28, 2025 at 2:39 PM Martin Uecker <ma.uec...@gmail.com> wrote: > Yes, forwards declarations are this simplest solution. > Forward declarations work until you get something complex. For example, if we want to support substructure fields in the attribute, you'd have to replicate the whole substructure's declaration in the forward decl. That becomes unwieldy when the substructure is very big:
struct foo { char *buf __counted_by_expr(struct bar { ... } sub; sub.a.b); struct bar { int x, y; struct baz { int b; /* 20 other elements */ } a; unsigned b1 : 1; unsigned b2 : 4; unsigned : 8; unsigned b3 : 2; /* and on and on... */ } sub; }; However, with delayed parsing, we wouldn't have to worry about forward declaring all of 'struct bar'. -bw > Another idea I mentioned before is to let __self.N have type > int, and then emit an error later if it has a type that > would change the type / meaning of the immediate > parent expression. > > This would allow all of the following: > > struct foo { > char * __counted_by_expr(__self.N) buf; > int N; > }; > struct foo { > char * __counted_by_expr(__self.N + 1L) buf; > long N; > }; > struct foo { > char * __counted_by_expr(__self.N * 2) buf; > int N; > }; > struct foo { > char * __counted_by_expr(__self.N + 2) buf; > char N; > }; > struct foo { > char * __counted_by_expr(__self.N + .M) buf; > int N; int M; > }; > struct foo { > char * __counted_by_expr((int)__self.N) buf; > double N; > }; > struct foo { > char * __counted_by_expr(3 * sizeof(__self.buf2)) buf; > char buf2[5]; > }; > struct foo { > char * __counted_by_expr(((struct bar *)__self.x)->z) buf; > struct bar *x; > }; > > > It would *not* allow: > > struct foo { > char * __counted_by_expr(__self.N + 1) buf; > long N; > }; > struct foo { > char * __counted_by_expr(__self.x->z) buf; > struct foo *x; > }; > > > But in this case you would get an explicit error: > > xyz:13.4: Type of `__self.N' needs to be known. Did you forget to > add a cast `(long)__self.N'? > > > > Martin > > > > > >