CC’ing gcc alias as well. 

Hi, Yeoul,

I think the key for when to  use the forward declaration syntax is:

When there is only one single identifier as the argument of counted_by 
attribute, 
There will be no possibility of scope conflict between different identifiers 
inside
the counted_by attribute, for such cases, we always look up the identifier 
inside
the structure. 

No need for the forward declaration syntax for such cases. 

This is the current behavior of counted_by attribute with single identifier, 
this behavior
remains unchanged. 

However, when the argument of counted_by attribute is  an expression, there 
might be
multiple identifiers inside counted_by attribute, the scope conflict between 
different
identifiers inside the counted_by attribute becomes possible, for such cases, 
forward declarations 
are necessary to specify which identifiers inside the counted_by attribute 
should be looked
up inside the structure. The identifiers that are not listed in the forward 
declarations will be
looked up according to the default C scoping rules . 

Forward declarations inside the counted_by attributes serve two purposes:

1. Explicitly specify which identifiers should be looked up inside the 
structure. (Similar purpose as 
    the new __self keyword we proposed previously).
2. Resolve the real forward declaration issue as we identified previously. 

In addition to the above 2, the forward declarations syntax is user-friendly 
and easy to be understood.
It keeps the default C scoping rules. And at the same time it’s also can be 
used for C++ as well. 

So, I think this might be a nice compromised new syntax. 

More in below to answer your questions:

> On Apr 2, 2025, at 19:52, Yeoul Na <yeoul...@apple.com> wrote:
> 
> Hi Qing and Bill,
> 
> Thanks for trying to converge on the solution for this problem.
> 
> @Bill: So your proposal allows referring to a member for simple declaration 
> reference like this:
> 
> constexpr int len = 20;
> struct s {
>   int len;
>   int *__counted_by(len) buf; // this continues to be member ‘len’, not 
> global ‘len'  
> };
> 
> 
> Requires forward declarations for these cases
> - forward referencing:
> 
> constexpr int len = 20;
> struct s {
>   int *__counted_by(int len; len) buf; 
>   int len; 
> };

I think that in the above example, the forward declaration is not needed if the 
user’s intention is to use
the member “len” instead of the global “len”. 

However, if the user tries to use the global “len” instead of the member “len”, 
then he need to use the 
Following syntax:

constexpr int len = 20;
struct s {
  int *__counted_by(len+0) buf; 
  int len; 
};

In the above, the argument inside counted_by is an expression, however, there 
is NO any forward declaration,
Then the identifier inside this expression will be looked up per the default C 
scoping rule.
Jacub Jelinek from GCC community mentioned this in a very early email in the 
GCC discussion. 

https://gcc.gnu.org/pipermail/gcc-patches/2025-March/677123.html


> - arithmetic expressions, etc.
> 
> constexpr int len = 20;
> constexpr int scale = 4;
> struct s {
>   int scale; 
>   int len;
>   int *__counted_by(int scale; int len; len * scale) buf; 
> };

Yes. This is correct. As long as the counted_by argument is an expression, 
forward declarations are needed
 to specify which identifiers should be looked up inside the structure. 

> 
> Is that a correct summary?
> If so, I’m curious what is the expected behavior for this:
> 
> constexpr int len = 20;
> constexpr int scale = 4;
> struct s {
>   int scale; 
>   int len;
>   int *__counted_by(len * scale) buf; 
> };
> 

In the above, since the argument is an expression, but there is no forward 
declaration inside the counted_by,
The identifiers “len” and “scale” are all looked up through the default C 
scoping, i.e, outside of the structure.

> 
>> So, I will go with the compromised syntax as suggested by Bill and Martin.
> 
> 
> @Bill @Qing Before doing that, this also needs Clang community to be on 
> board. I see Bill’s proposal is only being discussed in the GCC list. 
> However, adding a forward declaration within attributes will also affect 
> Clang attributes such as ‘guarded_by’, so could you please start an RFC in 
> Clang community as well and get support from there?
> 
> I will still have some more questions and other suggestions on your proposal 
> that I’d like to discuss once you start some thread in Clang. 
> 
> Also, the attributes (‘counted_by’ and friends, and ‘guarded_by’) are also 
> used for function parameters. Are you suggesting to use the forward 
> declaration for function parameters as well? Or this is just for structs?

From my understanding, as I mentioned in the above,  the purpose of the forward 
declarations 
inside counted_by attribute are:

1. Explicitly specify which identifiers should be looked up inside the 
structure. (Similar purpose as 
    the new __self keyword we proposed previously).
2. Resolve the real forward declaration issue as we identified previously. 

So, I am not quite sure whether this fit function parameters or not. 

But I do see that GCC support this as an extension for the purpose of VLA, 
please see:

https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

CLANG doesn’t support this GCC extension?

Qing

> 
> So this is another reason to get feedback from Clang. Clang doesn’t support 
> forward declarations for parameters, so this proposal would also affect 
> whether we bring forward declarations to Clang or not. FYI. we will be 
> proposing a counter-proposal to the C standard for the next meeting to allow 
> forward referencing without requiring a forward declaration.
> 
>> Rationale: This alleviates the issues of "double parsing" for
>> compilers that aren't able to handle it. (We can also remove the
>> '-fexperimental-late-parse-attributes' flag in Clang.)
> 
> @Bill We should NOT just remove this flag in Clang because the guarded_by 
> attribute is already relied on this in C and also ‘counted_by' on function 
> parameters will still rely on it.
> 
> Cheers,
> Yeoul


Reply via email to