On Mon, Jun 23, 2025 at 4:44 PM Qing Zhao <qing.z...@oracle.com> wrote: > > gcc/ChangeLog: > > * tree-object-size.cc (access_with_size_object_size): Update comments > for pointers with .ACCESS_WITH_SIZE. > (collect_object_sizes_for): Propagate size info through GIMPLE_ASSIGN > for pointers with .ACCESS_WITH_SIZE. > > gcc/testsuite/ChangeLog: > > * gcc.dg/pointer-counted-by-4-char.c: New test. > * gcc.dg/pointer-counted-by-4-float.c: New test. > * gcc.dg/pointer-counted-by-4-struct.c: New test. > * gcc.dg/pointer-counted-by-4-union.c: New test. > * gcc.dg/pointer-counted-by-4.c: New test. > * gcc.dg/pointer-counted-by-5.c: New test. > * gcc.dg/pointer-counted-by-6.c: New test. > * gcc.dg/pointer-counted-by-7.c: New test. > --- > .../gcc.dg/pointer-counted-by-4-char.c | 6 ++ > .../gcc.dg/pointer-counted-by-4-float.c | 6 ++ > .../gcc.dg/pointer-counted-by-4-struct.c | 10 +++ > .../gcc.dg/pointer-counted-by-4-union.c | 10 +++ > gcc/testsuite/gcc.dg/pointer-counted-by-4.c | 77 +++++++++++++++++++ > gcc/testsuite/gcc.dg/pointer-counted-by-5.c | 56 ++++++++++++++ > gcc/testsuite/gcc.dg/pointer-counted-by-6.c | 54 +++++++++++++ > gcc/testsuite/gcc.dg/pointer-counted-by-7.c | 30 ++++++++ > gcc/tree-object-size.cc | 18 ++++- > 9 files changed, 264 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-4.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-5.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-6.c > create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-7.c > > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c > new file mode 100644 > index 00000000000..c404e5b8cce > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c > @@ -0,0 +1,6 @@ > +/* Test the attribute counted_by for pointer field and its usage in > + * __builtin_dynamic_object_size. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > +#define PTR_TYPE char > +#include "pointer-counted-by-4.c" > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c > new file mode 100644 > index 00000000000..383d8fb656d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c > @@ -0,0 +1,6 @@ > +/* Test the attribute counted_by for pointer field and its usage in > + * __builtin_dynamic_object_size. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > +#define PTR_TYPE float > +#include "pointer-counted-by-4.c" > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c > new file mode 100644 > index 00000000000..50246d29477 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c > @@ -0,0 +1,10 @@ > +/* Test the attribute counted_by for pointer field and its usage in > + * __builtin_dynamic_object_size. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > +struct A { > + int a; > + char *b; > +}; > +#define PTR_TYPE struct A > +#include "pointer-counted-by-4.c" > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c > new file mode 100644 > index 00000000000..e786d996147 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c > @@ -0,0 +1,10 @@ > +/* Test the attribute counted_by for pointer field and its usage in > + * __builtin_dynamic_object_size. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > +union A { > + int a; > + float b; > +}; > +#define PTR_TYPE union A > +#include "pointer-counted-by-4.c" > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-4.c > new file mode 100644 > index 00000000000..11ae6288030 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4.c > @@ -0,0 +1,77 @@ > +/* 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" > +#ifndef PTR_TYPE > +#define PTR_TYPE int > +#endif > +struct pointer_array { > + int b; > + PTR_TYPE *c; > +} *p_array; > + > +struct annotated { > + PTR_TYPE *c __attribute__ ((counted_by (b))); > + int b; > +} *p_array_annotated; > + > +struct nested_annotated { > + PTR_TYPE *c __attribute__ ((counted_by (b))); > + struct { > + union { > + int b; > + float f; > + }; > + int n; > + }; > +} *p_array_nested_annotated; > + > +void __attribute__((__noinline__)) setup (int normal_count, int attr_count) > +{ > + p_array > + = (struct pointer_array *) malloc (sizeof (struct pointer_array)); > + p_array->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * normal_count); > + p_array->b = normal_count; > + > + p_array_annotated > + = (struct annotated *) malloc (sizeof (struct annotated)); > + p_array_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * > attr_count); > + p_array_annotated->b = attr_count; > + > + p_array_nested_annotated > + = (struct nested_annotated *) malloc (sizeof (struct nested_annotated)); > + p_array_nested_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * > attr_count); > + p_array_nested_annotated->b = attr_count; > + > + return; > +} > + > +void __attribute__((__noinline__)) test () > +{ > + EXPECT(__builtin_dynamic_object_size(p_array->c, 1), -1); > + EXPECT(__builtin_dynamic_object_size(p_array_annotated->c, 1), > + p_array_annotated->b * sizeof (PTR_TYPE)); > + EXPECT(__builtin_dynamic_object_size(p_array_nested_annotated->c, 1), > + p_array_nested_annotated->b * sizeof (PTR_TYPE)); > +} > + > +void cleanup () > +{ > + free (p_array->c); > + free (p_array); > + free (p_array_annotated->c); > + free (p_array_annotated); > + free (p_array_nested_annotated->c); > + free (p_array_nested_annotated); > +} > + > +int main(int argc, char *argv[]) > +{ > + setup (10,10); > + test (); > + DONE (); > + cleanup (); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-5.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-5.c > new file mode 100644 > index 00000000000..567ad9fa4bd > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-5.c > @@ -0,0 +1,56 @@ > +/* Test the attribute counted_by for pointer fields and its usage in > + * __builtin_dynamic_object_size: when the counted_by field is negative. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#include "builtin-object-size-common.h" > + > +struct annotated { > + int b; > + int *c __attribute__ ((counted_by (b))); > +} *array_annotated; > + > +struct nested_annotated { > + int *c __attribute__ ((counted_by (b))); > + struct { > + union { > + int b; > + float f; > + }; > + int n; > + }; > +} *array_nested_annotated; > + > +void __attribute__((__noinline__)) setup (int attr_count) > +{ > + array_annotated > + = (struct annotated *)malloc (sizeof (struct annotated)); > + array_annotated->b = attr_count; > + > + array_nested_annotated > + = (struct nested_annotated *)malloc (sizeof (struct nested_annotated)); > + array_nested_annotated->b = attr_count - 1; > + > + return; > +} > + > +void __attribute__((__noinline__)) test () > +{ > + EXPECT(__builtin_dynamic_object_size(array_annotated->c, 1), 0); > + EXPECT(__builtin_dynamic_object_size(array_nested_annotated->c, 1), 0); > +} > + > +void cleanup () > +{ > + free (array_annotated); > + free (array_nested_annotated); > +} > + > +int main(int argc, char *argv[]) > +{ > + setup (-10); > + test (); > + DONE (); > + cleanup (); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-6.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-6.c > new file mode 100644 > index 00000000000..fb1d8620afc > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-6.c > @@ -0,0 +1,54 @@ > +/* Test the attribute counted_by for pointer fields and its usage in > + * __builtin_dynamic_object_size: when the type of the pointer > + * is casting to another type. */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +#include "builtin-object-size-common.h" > + > +typedef unsigned short u16; > + > +struct info { > + u16 data_len; > + char *data __attribute__((counted_by(data_len))); > +}; > + > +struct foo { > + int a; > + int b; > +}; > + > +static __attribute__((__noinline__)) > +struct info *setup () > +{ > + struct info *p; > + size_t bytes = 3 * sizeof(struct foo); > + > + p = (struct info *) malloc (sizeof (struct info)); > + p->data = (char *) malloc (bytes); > + p->data_len = bytes; > + > + return p; > +} > + > +static void > +__attribute__((__noinline__)) report (struct info *p) > +{ > + struct foo *bar = (struct foo *)p->data; > + EXPECT(__builtin_dynamic_object_size((char *)(bar + 1), 1), sizeof (struct > foo) * 2); > + EXPECT(__builtin_dynamic_object_size((char *)(bar + 2), 1), sizeof (struct > foo)); > +} > + > +void cleanup (struct info *p) > +{ > + free (p->data); > + free (p); > +} > + > +int main(int argc, char *argv[]) > +{ > + struct info *p = setup(); > + report(p); > + cleanup (p); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-7.c > b/gcc/testsuite/gcc.dg/pointer-counted-by-7.c > new file mode 100644 > index 00000000000..01addbb857d > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-7.c > @@ -0,0 +1,30 @@ > +/* Additional test of 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; > + 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 (); > +} > diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc > index f348673ae75..4e9ddde49c1 100644 > --- a/gcc/tree-object-size.cc > +++ b/gcc/tree-object-size.cc > @@ -773,10 +773,12 @@ addr_object_size (struct object_size_info *osi, > const_tree ptr, > 4th argument TYPE_OF_SIZE: A constant 0 with its TYPE being the same as > the TYPE > of the object referenced by REF_TO_SIZE > 6th argument: A constant 0 with the pointer TYPE to the original flexible > - array type. > + array type or pointer field type. > > The size of the element can be retrived from the TYPE of the 6th argument > - of the call, which is the pointer to the array type. */ > + of the call, which is the pointer to the original flexible array type or > + the type of the original pointer field. */ > + > static tree > access_with_size_object_size (const gcall *call, int object_size_type) > { > @@ -786,7 +788,7 @@ access_with_size_object_size (const gcall *call, int > object_size_type) > > gcc_assert (gimple_call_internal_p (call, IFN_ACCESS_WITH_SIZE)); > /* The type of the 6th argument type is the pointer TYPE to the original > - flexible array type. */ > + flexible array type or to the original pointer type. */ > tree pointer_to_array_type = TREE_TYPE (gimple_call_arg (call, 5)); > gcc_assert (POINTER_TYPE_P (pointer_to_array_type)); > tree element_type = TREE_TYPE (TREE_TYPE (pointer_to_array_type)); > @@ -1854,6 +1856,16 @@ collect_object_sizes_for (struct object_size_info > *osi, tree var) > if (TREE_CODE (rhs) == SSA_NAME > && POINTER_TYPE_P (TREE_TYPE (rhs))) > reexamine = merge_object_sizes (osi, var, rhs); > + /* Handle the following stmt #2 to propagate the size from the > + stmt #1 to #3: > + 1 _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B); > + 2 _5 = *_1; > + 3 _6 = __builtin_dynamic_object_size (_5, 1); > + */ > + else if (TREE_CODE (rhs) == MEM_REF > + && POINTER_TYPE_P (TREE_TYPE (rhs)) > + && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
&& integer_zerop (TREE_OPERAND (rhs, 1)) ? > + reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, > 0)); > else > expr_object_size (osi, var, rhs); > } > -- > 2.31.1 >