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 (); } Martin