> On Jul 29, 2025, at 11:52, Martin Uecker <ma.uec...@gmail.com> wrote: > > Am Dienstag, dem 29.07.2025 um 13:49 +0000 schrieb Qing Zhao: >> >>> On Jul 28, 2025, at 17:39, Martin Uecker <ma.uec...@gmail.com> wrote: >>> >>> Am Montag, dem 28.07.2025 um 20:48 +0000 schrieb Qing Zhao: >>>> >>>>> On Jul 28, 2025, at 16:09, Martin Uecker <ma.uec...@gmail.com> wrote: >>>>> >>>>>> > > ... > >>>>>> Ex 6) >>>>>> constexpr int n = 10; >>>>>> struct s { >>>>>> int *__counted_by_expr(n + 1) ptr; // resolves to global `n`; okay, no >>>>>> matching member name >>>>>> }; >>>>>> >>>>>> Or in case, people prefer forward declaration inside >>>>>> `__counted_by_expr()`, the similar rule can apply to achieve the same >>>>>> goal. >>>>>> >>>>> >>>>> Thank you Yeoul! >>>>> >>>>> I think it is a reasonable compromise. >>>> >>>> Yes, I agree. -:) >>>> >>>> It adds two new keywords in both C and C++ (__self and __global_ref) to >>>> explicitly mark the scopes for the variables inside the attribute. >>>> will definitely resolve the lookup scope ambiguity issue in both C and >>>> C++. >>>> >>>> However, it will not resolve the issue when the counted_by field is >>>> declared After the pointer field. >>>> So, forward declarations is still needed to resolve this issue, I think. >>> >>> Yes, forwards declarations are this simplest solution. >>> >>> >>> 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. >> >> Yes, this is reasonable too. >> >> However, one of the major issue with it is, the user has to change the type >> of all the counted_by field to “int”. Not sure whether this is easy to do >> or not >> for a large application. > > I agree that this would not make sense. Sorry, I did not explain > this idea well. > > The idea is that we parse assuming it has type "int", but then it is > ok to have a different type as long as this would not invalidate or > previous analysis. Only when the *parent* expression would change > type, then this is an error later when we know the real type. > > So for example it can have type "bool", "char", "short" because these > would promote to an integer, so inserting them for __self.N would > not invalidate or previous analysis that was done assuming it was > an "int". It turns out that there are many other cases where the > type does not matter (e.g. see below) and which would just work. >
Oh, yeah. My bad. Sorry for my stupid question. -:). Qing > > Martin > > > > > >> >> Qing >>> >>> 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