On Wed, Jul 23, 2025 at 04:28:36PM +0000, Qing Zhao wrote:
>
>
> > On Jul 23, 2025, at 03:30, Kees Cook <[email protected]> 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