On Mon, Apr 14, 2025 at 1:56 PM Qing Zhao <qing.z...@oracle.com> wrote: > > Hi, Bill, > > Thanks for your new proposal. > > If I understand correctly, this new proposal basically is back to one of our > previous proposal: > > Adding a new structure scoping for counted_by attribute into C; > > With this approach, there is one new structure scoping added to C, and this > new scope > will shadow other scopes in the current C. > > The identifiers inside the counted_by attribute will be looked up within this > new structure scope first. > Conflicted local or global variables need to be prefixed with special builtin > to explicitly specify its scope. > > Is this understanding correctly? > Yes, in a sense. I called it a "pseudo" struct scope, because it's not fully fleshed out and is limited to very specific instances with very specific behavior.
> My opinion on this: > > 1. Personally, as I mentioned multiple times, I think that this might be the > cleanest solution; > If other people agree on this, I am happy to go with this. -:) > :-) > 2. However, my understanding from our previous long discussion is: > Adding a new structure scope to C (even it’s only for counted_by > attribute) should not be done without > Having a clear specification and support from WG14. > > Please refer to the following: > > https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679922.html. > https://gcc.gnu.org/pipermail/gcc-patches/2025-April/679923.html. > > Martin and Joseph, what’s your opinion on this proposal? > I should point out that using the forward declaration syntax could cause errors with macro expansions. For example, #define FOO (len + 42) struct A { int *buf __counted_by_expr(size_t len; len << FOO); int len; }; The 'len' from the macro expansion will use the 'len' in the struct, which may not be what was intended, but would nevertheless be quietly accepted. -bw > Thanks. > > Qing > > On Apr 14, 2025, at 13:12, Bill Wendling <isanb...@gmail.com> wrote: > > > > Soooo....After being on a mini-vacation and thinking about this more, > > I'm a bit less satisfied with the current proposal. The main issue is > > that we have seemingly two lookup rules based on which attribute is > > used (counted_by vs. counted_by_expr). > > > > 1. counted_by: We expect an expression that's a lone identifier. > > Here, we use a pseudo-struct scope to resolve that identifier. > > ("Pseudo" because it's not fully defined in the standard but created > > for this feature alone.) > > > > 2. counted_by_expr: Any identifiers that appear in the struct need > > to be forward declared. If they aren't, the normal lookup rules apply. > > > > Now, I don't think this will be necessarily confusing to the > > programmer, but it's inconsistent. In other words, either 'counted_by' > > *must* forward declare the in-structure identifier or neither must. > > > > It's also probable that most expressions will use in-structure > > identifiers, with the occasional enum or macro. (I'm going off of > > Yeoul's assertion that they've implemented this successfully on large > > code bases and haven't had to make allowances for global identifiers.) > > > > My counter proposal then is to do something like this: > > > > 1. The syntax needs to be unambiguous. > > 2. Identifier lookup must be consistent between the two attribute forms. > > 3. The common use case should take the least amount of code to write. > > (More of a "nice to have".) > > > > Therefore, I suggest the following rules, that are more-or-less the > > reverse of the current proposal's rules: > > > > - All untagged identifiers are assumed to be within the structure. If > > they aren't found in the struct, it's an error. > > - All globals (i.e. identifiers not in the struct) must be referenced > > via a special tag or a builtin (e.g. __builtin_global_ref()). The tag > > or builtin follow current scoping rules---i.e. it may pick up a shadow > > variable rather than the global. > > > > Examples: > > > > [Assume a builtin called '__builtin_global_ref' that takes an > > expression where every identifier within that expression is assumed > > "global".] > > > > struct A { > > int *buf __counted_by(len); // 'len' *must* be in the struct. > > int len; > > }; > > > > constexpr int len = 42; > > struct B { > > int *buf __counted_by(__builtin_global_ref(len)); // 'len' is a global. > > }; > > > > enum { PADDING = 42 }; > > struct C { > > int *buf __counted_by_expr(len * __builtin_global_ref(PADDING)); > > int len; > > }; > > > > #define PADDING_EXPR __builtin_gloal_ref(len) + 42 > > struct D { > > int *buf __counted_by_expr(len * PADDING_EXPR); > > // PADDING_EXPR is expanded and that 'len' is not in the structure. > > int len; > > }; > > > > #define PADDING_EXPR len + 42 > > struct E { > > int *buf __counted_by_expr(len * __builtin_global_ref(PADDING_EXPR)); > > // PADDING_EXPR is expanded and that 'len' is not in the structure. > > int len; > > }; > > > > There is the issue that the __builtin_global_ref() in 'struct E' may > > appear to cause the sub-expression to have a higher affinity than the > > multiplication but it doesn't. That may or may not be a programmer > > error, but one to be aware of nonetheless. > > > > -bw >