On Wed, Jul 23, 2025 at 04:28:36PM +0000, Qing Zhao wrote: > > > > On Jul 23, 2025, at 03:30, Kees Cook <k...@kernel.org> wrote: > > > > > > How would GCC want to define the syntax for expressions here? I still > > think it should be possible to wire up something that matches it in > > Clang, even if it is a "redundant" syntax within Clang (i.e. Clang can > > support 2 way to handle expressions, GCC has 1, and Linux will use the > > common way). > > If that’s acceptable, in GCC alias, we have agreed on the following > compromised solution > after a long and thorough discussion based on one of Bill’s proposal: > > 1. For a lone identifier that refers to a structure field, keep the current > counted_by syntax as FAM: > > counted_by (identifier) > > struct s { > int len; > int *buf __attribute__((counted_by(len))); // this “len” continues to be > member ‘len’. > }; > > 2. For simple expressions inside the counted_by attribute, a new attribute > will be provided > > counted_by_exp (simple expression) > > Inside this simple expression, forward declarations will be used to resolve > the following two issues: > > A. Structure-level scoping that does not exist in C language; > B. Fields that are declared after the pointer field. > > For example: > > constexpr int len = 20; > constexpr int scale = 4; > struct s { > int scale; > int *buf __attribute__((counted_by_exp(int scale; int len; len * scale))); > > // len and scale should be the fields inside the structure due to the > forward declarations > int len; > }; > > > I noted that the forward declarations has been strongly rejected in the > discussion inside CLANG, but > didn’t find and understand what’s the root reason for the “strong rejection”. > > > > > > The two things I've seen proposed during all of these discussions that > > look like they should be workable are either: > > > > 1) making expression-using attributes _struct_ attributes, not struct > > _member_ attributes. (i.e. parsing of the struct has ended) > > This should resolve the issue B I listed in the above, but still cannot > resolve the scoping issue. > If there is a conflict between a global and a field, which one to choose?
If it wasn't forward declared, then isn't it the global then? IIRC Apple rejected this as too error-prone, and I think it's a reasonable point: we don't want to add new ambiguities to the language, so we likely need some way to say "I want exactly the global". > > 2) using a callback for expressions (no late parsing needed) > > I don’t like this approach due to following reasons: > 1. both user interface and compiler interface are not friendly; I think this is improved by my proposal to make the declaration internally implemented: a bit of "magic", but it has a single syntax, so there is no ambiguity, and avoids redundancy since the callback will always have exactly the same prototype pattern: struct S { int array[] __counted_by_callback(how_many); }; When seeing "how_many" here, a declaration is internally processed as: static inline size_t __attribute__((pure)) __S_array_counted_by(struct S *instance); And then after the struct the user can do whatever: static inline size_t __attribute__((pure)) __S_array_counted_by(struct S *instance) { { return global_var; } > 2. Arbitrary function call might be abused by users later; This part I haven't understood. What does "abused" mean in this case? The best I can understand is that the "pure" attribute behavior requirements get violated (though isn't this user error?). Do you mean something else? > 3. It’s very hard to be developed to a feature that can be standardized in > the future. Why is that? > > > > I'm well aware that Apple's implementation will not do either of these, > > but I'm confident Clang can support the additional syntax -- it should > > be possible to provide both, especially since it would be a "GCC > > compatibility" issue. :) > > If Clang can provide a GCC compatible counted_by_exp attribute, then the > problem can be > Resolved for linux kernel. Agreed. AFAICT, the infrastructure will exist in Clang already to support counted_by_exp(); it is just a different way to specify the same thing. -- Kees Cook