> On Dec 5, 2024, at 17:31, Martin Uecker <uec...@tugraz.at> wrote:
> 
> Am Donnerstag, dem 05.12.2024 um 21:09 +0000 schrieb Qing Zhao:
>> 
>>> On Dec 3, 2024, at 10:29, Qing Zhao <qing.z...@oracle.com> wrote:
> 
> ....
> 
>>>> 
>>>>>> 
>>>>>>>> 
>>>>>>>> It would be clearer if you the syntax ".n" which resembles
>>>>>>>> the syntax for designated initializers that is already used
>>>>>>>> in initializers to refer to struct members.
>>>>>>>> 
>>>>>>>> constexpr int n;
>>>>>>>> struct foo {
>>>>>>>> {
>>>>>>>> char (*p)[n] __attribute__ ((counted_by (.n))
>>>>>>>> int n;
>>>>>>>> }
>>>>>>>> 
>>>>>>> Yes, I agree.
>>>>>>>> 
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> There is one important additional requirement:
>>>>>>>>>>> 
>>>>>>>>>>> x->n, x->p can ONLY be changed by changing the whole structure at 
>>>>>>>>>>> the same time. 
>>>>>>>>>>> Otherwise, x->n might not be consistent with x->p.
>>>>>>>>>> 
>>>>>>>>>> By itself, this would still not fix the issue I pointed out.
>>>>>>>>>> 
>>>>>>>>>> struct foo x;
>>>>>>>>>> x = .. ; // set the whole structure
>>>>>>>>>> char *p = x->p;
>>>>>>>>>> x = ... ; // set the whole structure
>>>>>>>>>> 
>>>>>>>>>> What is the bound for 'p' ?  
>>>>>>>>> 
>>>>>>>>> Since p was set to the pointer field of the old structure, then the 
>>>>>>>>> bound of it should be the old bound.
>>>>>>>>>> With current rules it would be the old bound.
>>>>>>>>> 
>>>>>>>>> I thought that this should be the correct behavior, isn’t it?
>>>>>>>> 
>>>>>>>> Yes, sorry, what I meant was "with the current rules it would be
>>>>>>>> the *new* bound”.
>>>>>>> 
>>>>>>> struct foo x;
>>>>>>> x=… ;  // set the whole structure 1
>>>>>>> char *p = x->p;
>>>>>>> x=… ;  // set the whole structure 2
>>>>>>> 
>>>>>>> In the above, when “set the whole structure 1”, x1, x1->n and x1->p are 
>>>>>>> set at the same time;
>>>>>>> After *p = x->p;    the pointer “p” is pointing to “x1->p”, it’s bound 
>>>>>>> is “x1->n”;
>>>>>> 
>>>>>> I agree.
>>>>>>> 
>>>>>>> Then when “set the whole structure 2”, x2 is different than x1,  x2->n 
>>>>>>> and x2->p are set at the same time, the pointer
>>>>>>> ‘p’ still points to “x1->p”, therefore it’s bound should be “x1->n”. 
>>>>>>> 
>>>>>>> So, as long as the whole structure is set at the same time, should be 
>>>>>>> fine. 
>>>>>>> 
>>>>>>> Do I miss anything here?
>>>>>> 
>>>>>> I was talking aout the pointer "p" which was obtained before setting the
>>>>>> struct the second time in
>>>>>> 
>>>>>> char *p = x->p;
>>>>>> 
>>>>>> This pointer is still set to x1->p but the bound refers to x.n which is 
>>>>>> now set to x2->n.
>>>>> 
>>>>> You mean:
>>>>> 
>>>>> struct foo x;
>>>>> x=… ;  // set the whole structure 1
>>>>> char *p = x->p;
>>>>> x=… ;  // set the whole structure 2
>>>>> p[index] = 10;   // at this point, p’s bound is x2->n, not x1->n? 
>>>>> 
>>>>> Yes, you are right here. 
>>>>> 
>>>>> So, is there similar problem with the corresponding language extension? 
>>>>> 
>>>> 
>>>> The language extension does not exist yet, so there is no problem.
>>> Yeah, I should mention this as “corresponding future language extension” -:)
>>>> 
>>>> But I hope we will get it and then specify it so that this works
>>>> correctly without this footgun.
>>>> 
>>>> Of course, if GCC gets the "counted_by" attribute wrong, there will
>>>> be arguments later in WG14 why the feature is then different to it.
>>> 
>>> I think that we need to resolve this issue first in the design of 
>>> “counted_by” for pointer fields. 
>>> I guess that we might need to come up with some additional limitations for 
>>> using the “counted_by”
>>> attribute for pointer fields at the source code level in order to avoid 
>>> such potential error.  But not
>>> sure what exactly the additional limitation should be at this moment.
>>> 
>>> Need some study here.
>> 
>> Actually, I found out that this is really not a problem with the current 
>> design, for the following new testing case I added for my current 
>> implementation of the counted_by for pointer field:
>> 
>> [ gcc.dg]$ cat pointer-counted-by-7.c
>> /* Test the attribute counted_by for pointer field and its usage in
>> * __builtin_dynamic_object_size.  */ 
>> /* { dg-do run } */
>> /* { dg-options "-O2" } */
>> 
>> #include "builtin-object-size-common.h"
>> 
>> struct annotated {
>>  int b;
>>  int *c __attribute__ ((counted_by (b)));
>> };
>> 
>> struct annotated *__attribute__((__noinline__)) setup (int attr_count)
>> {
>>  struct annotated *p_array_annotated
>>    = (struct annotated *) malloc (sizeof (struct annotated));
>>  p_array_annotated->c = (int *) malloc (sizeof (int) * attr_count);
>>  p_array_annotated->b = attr_count;
>> 
>>  return p_array_annotated;
>> }
>> 
>> 
>> int main(int argc, char *argv[])
>> {
>>  struct annotated *x = setup (10);     
>>  int *p = x->c;
>>  x = setup (20);
>>  EXPECT(__builtin_dynamic_object_size (p, 1), 10 * sizeof (int));
>>  EXPECT(__builtin_dynamic_object_size (x->c, 1), 20 * sizeof (int));
>>  DONE ();
>> }
>> 
>> This test case passed without any issue. 
>> 
>> Our previous introduction of the new internal function .ACCESS_WITH_SIZE 
>> already resolved this issue.
>> 
>> So, I think that as long as the whole structure is set at the same time, 
>> should be fine. 
>> 
>> Let me know if you have more comment here.
> 
> I think the relevant scenario is where you assign the struct and
> not a pointer to the struct, i.e. something like the following:
> 
> #include "builtin-object-size-common.h"
> 
> struct annotated {
>  int b;
>  int *c __attribute__ ((counted_by (b)));
> };
> 
> struct annotated __attribute__((__noinline__)) setup (int attr_count)
> {
>  struct annotated p_array_annotated;
>  p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count);
>  p_array_annotated.b = attr_count;
> 
>  return p_array_annotated;
> }
> 
> 
> int main(int argc, char *argv[])
> {
>  struct annotated x = setup (10);     
>  int *p = x.c;
>  x = setup (20);
>  EXPECT(__builtin_dynamic_object_size (p, 1), 10 * sizeof (int));
>  EXPECT(__builtin_dynamic_object_size (x.c, 1), 20 * sizeof (int));
>  DONE ();
> }
> 

With the above testing case, my current implementation based on 
.ACCESS_WITH_SIZE succeed without any issue.  -:)
The design of .ACCESS_WITH_SIZE already resolved this issue.

Qing
> Martin
> 
> 
> 

Reply via email to