> On Jul 28, 2025, at 2:40 PM, Bill Wendling <mo...@google.com> wrote:
> 
> On Mon, Jul 28, 2025 at 1:48 PM Qing Zhao <qing.z...@oracle.com 
> <mailto:qing.z...@oracle.com>> wrote:
>>> On Jul 28, 2025, at 16:09, Martin Uecker <ma.uec...@gmail.com> wrote:
>>> Am Montag, dem 28.07.2025 um 11:18 -0700 schrieb Yeoul Na:
>>>>> On Jul 28, 2025, at 10:27 AM, Qing Zhao <qing.z...@oracle.com> wrote:
>>>>>> On Jul 26, 2025, at 12:43, Yeoul Na <yeoul...@apple.com> wrote:
>>>>>>> On Jul 24, 2025, at 3:52 PM, Kees Cook <k...@kernel.org> wrote:
>>>>>>> 
>>>>>>> On Thu, Jul 24, 2025 at 04:26:12PM +0000, Aaron Ballman wrote:
>>>>>>>> Ah, apologies, I wasn't clear. My thinking is: we're (Clang folks)
>>>>>>>> going to want it to work in C++ mode because of shared headers. If it
>>>>>>>> works in C++ mode, then we have to figure out what it means with all
>>>>>>>> the various C++ features that are possible, not just the use cases
>>>>>>> 
>>>>>>> I am most familiar with C, so I may be missing something here, but if
>>>>>>> -fbounds-safety is intended to be C only, then why not just make it
>>>>>>> unrecognized in C++?
>>>>>> 
>>>>>> The bounds safety annotations must also be parsable in C++. While C++ 
>>>>>> can get bounds checking by using std::span instead of raw pointers, 
>>>>>> switching to std::span breaks ABI. Therefore,
>>>>>> in many situations, C++ code must continue to use raw pointers—for 
>>>>>> example, when interoperating with C code by sharing headers with C. In 
>>>>>> such cases, bounds annotations can help close
>>>>>> safety gaps in raw pointers.
>>>>> 
>>>>> -fbound-safety feature was initially proposed as an C extension, So, it’s 
>>>>> natural to make it compatible with C language, not C++.
>>>>> If C++ also need such a feature, then an extension to C++ is needed too.
>>>>> If a consistent syntax for this feature can satisfy both C and C++,  that 
>>>>> will be ideal.
>>>>> However, if  providing such consistent syntax requires major changes to C 
>>>>> language,
>>>>> ( a new name lookup scope, and late parsing), it might be a good idea to 
>>>>> provide different syntax for C and C++.
>>>> 
>>>> 
>>>> So the main problem here is when the "same code” will be parsed in both in 
>>>> C and C++, which is quite common in practice.
>>>> 
>>>> Therefore, we need a way to reasonably write code that works both C and 
>>>> C++.
>>>> 
>>>> From my perspective, that means:
>>>> 
>>>> 1. The same spelling doesn’t “silently" behave differently in C and C++.
>>>> 2. At least the most common use cases (i.e., __counted_by(peer)) should be 
>>>> able to be written the same way in C and C++, without ceremony.
>>>> 
>>>> Here is our compromise proposal that meets these requirements, until we 
>>>> get blessing from the standard for a more elegant solution:
>>>> 
>>>> 1. `__counted_by(member)` keeps working as is: late parsing + name lookup 
>>>> finds the member name first
>>>> 2. `__counted_by_expr(expr)` uses a new syntax (e.g., __self), and is not 
>>>> allowed to use a name that matches the member name without the new syntax 
>>>> even if that would’ve resolved to a
>>>> global variable. Use something like  `__global_ref(id)` to disambiguate. 
>>>> This rule will prevent the confusion where `__counted_by_expr(id)` and 
>>>> `__counted_by(id)` may designate different
>>>> entities.
>>>> 
>>>> Here are the examples:
>>>> 
>>>> Ex 1)
>>>> constexpr int n = 10;
>>>> 
>>>> struct s {
>>>>  int *__counted_by(n) ptr; // resolves to member `n`; which matches the 
>>>> current behavior
>>>>  int n;
>>>> };
>>>> 
>>>> Ex 2)
>>>> constexpr int n = 10;
>>>> struct s {
>>>>  int *__counted_by_expr(n) ptr; // error: referring to a member name 
>>>> without “__self."
>>>>  int n;
>>>> };
>>>> 
>>>> Ex 3)
>>>> constexpr int n = 10;
>>>> struct s {
>>>>  int *__counted_by_expr(__self.n) ptr; // resolves to member `n`
>>>>  int n;
>>>> };
>>>> 
>>>> 
>>>> Ex 4)
>>>> constexpr int n = 10;
>>>> struct s {
>>>>  int *__counted_by_expr(__self.n + 1) ptr; // resolves to member `n`
>>>>  int n;
>>>> };
>>>> 
>>>> 
>>>> Ex 5)
>>>> constexpr int n = 10;
>>>> struct s {
>>>>  int *__counted_by_expr(__global_ref(n) + 1) ptr; // resolves to global `n`
>>>>  int n;
>>>> };
>>>> 
>>>> 
>>>> Ex 6)
>>>> constexpr int n = 10;
>>>> struct s {
>>>>  int *__counted_by_expr(n + 1) ptr; // resolves to global `n`; okay, no 
>>>> matching member name
>>>> };
>>>> 
>>>> Or in case, people prefer forward declaration inside 
>>>> `__counted_by_expr()`, the similar rule can apply to achieve the same goal.
>>>> 
>>> 
>>> Thank you Yeoul!
>>> 
>>> I think it is a reasonable compromise.
> 
> This was suggested months ago, so sure, seems reasonable.

I want to make sure we’re on the same page. Not sure which one you meant by 
being suggested months ago. This is different from previous proposals from GCC. 
The difference is when the unqualified name matches any member:

constexpr int n = 10;
struct s {
  int n;
  int *__counted_by_expr(n + 1) buf; // error; instead of silently picking up 
global `n` 
};

constexpr int n = 10;
struct s {
  int *__counted_by_expr(n + 1) buf; // error; instead of silently picking up 
global `n` 
  int n;
};

This restriction was important to meet the requirement that the same code is 
not interpreted differently in C and C++, and in the same category of 
attributes.

Yeoul

> How do we
> handle function calls, like the "byte swap" example Kees pointed out?
> 
>> Yes, I agree. -:)
>> 
>> It adds two new keywords in both C and C++ (__self and __global_ref) to 
>> explicitly mark the scopes for the variables inside the attribute.
>> will definitely resolve the lookup scope ambiguity issue in both C and C++.
>> 
>> However, it will not resolve the issue when the counted_by field is declared 
>> After the pointer field.
>> So, forward declarations is still  needed to resolve this issue, I think.
> 
> I suggest delayed parsing instead.
> 
> -bw

Reply via email to