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