Am Freitag, dem 06.12.2024 um 14:16 +0000 schrieb Qing Zhao: > > > 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.
Ok, thanks! But I am a bit confused, because it seems it behaves this way also for FAMs https://godbolt.org/z/64a6z4cna and I thought this was changed, i.e. so that the bounds track the current value of b for this case. But apparently I was mistaken. I am fine with the behavior as shown here. Martin > > Qing > > Martin > > > > > > > -- Univ.-Prof. Dr. rer. nat. Martin Uecker Graz University of Technology Institute of Biomedical Imaging