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
>

Reply via email to