On Fri, Apr 12, 2024 at 3:55 PM Qing Zhao <qing.z...@oracle.com> wrote: > > to carry the TYPE of the flexible array. > > Such information is needed during tree-object-size.cc. > > We cannot use the result type or the type of the 1st argument > of the routine .ACCESS_WITH_SIZE to decide the element type > of the original array due to possible type casting in the > source code.
OK. I guess technically an empty CONSTRUCTOR of the array type would work as well (as aggregate it's fine to have it in the call) but a constant zero pointer might be cheaper to have as it's shared across multiple calls. Richard. > gcc/c/ChangeLog: > > * c-typeck.cc (build_access_with_size_for_counted_by): Add the 6th > argument to .ACCESS_WITH_SIZE. > > gcc/ChangeLog: > > * tree-object-size.cc (access_with_size_object_size): Use the type > of the 6th argument for the type of the element. > > gcc/testsuite/ChangeLog: > > * gcc.dg/flex-array-counted-by-6.c: New test. > --- > gcc/c/c-typeck.cc | 11 +++-- > gcc/internal-fn.cc | 2 + > .../gcc.dg/flex-array-counted-by-6.c | 46 +++++++++++++++++++ > gcc/tree-object-size.cc | 16 ++++--- > 4 files changed, 66 insertions(+), 9 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/flex-array-counted-by-6.c > > diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc > index ff6685c6c4ba..0ea3b75355a4 100644 > --- a/gcc/c/c-typeck.cc > +++ b/gcc/c/c-typeck.cc > @@ -2640,7 +2640,8 @@ build_counted_by_ref (tree datum, tree subdatum, tree > *counted_by_type) > > to: > > - (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1)) > + (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1, > + (TYPE_OF_ARRAY *)0)) > > NOTE: The return type of this function is the POINTER type pointing > to the original flexible array type. > @@ -2652,6 +2653,9 @@ build_counted_by_ref (tree datum, tree subdatum, tree > *counted_by_type) > The 4th argument of the call is a constant 0 with the TYPE of the > object pointed by COUNTED_BY_REF. > > + The 6th argument of the call is a constant 0 with the pointer TYPE > + to the original flexible array type. > + > */ > static tree > build_access_with_size_for_counted_by (location_t loc, tree ref, > @@ -2664,12 +2668,13 @@ build_access_with_size_for_counted_by (location_t > loc, tree ref, > > tree call > = build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE, > - result_type, 5, > + result_type, 6, > array_to_pointer_conversion (loc, ref), > counted_by_ref, > build_int_cst (integer_type_node, 1), > build_int_cst (counted_by_type, 0), > - build_int_cst (integer_type_node, -1)); > + build_int_cst (integer_type_node, -1), > + build_int_cst (result_type, 0)); > /* Wrap the call with an INDIRECT_REF with the flexible array type. */ > call = build1 (INDIRECT_REF, TREE_TYPE (ref), call); > SET_EXPR_LOCATION (call, loc); > diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc > index e744080ee670..34e4a4aea534 100644 > --- a/gcc/internal-fn.cc > +++ b/gcc/internal-fn.cc > @@ -3411,6 +3411,8 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt) > 1: read_only > 2: write_only > 3: read_write > + 6th argument: A constant 0 with the pointer TYPE to the original flexible > + array type. > > Both the return type and the type of the first argument of this > function have been converted from the incomplete array type to > diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-6.c > b/gcc/testsuite/gcc.dg/flex-array-counted-by-6.c > new file mode 100644 > index 000000000000..65fa01443d95 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-6.c > @@ -0,0 +1,46 @@ > +/* Test the attribute counted_by and its usage in > + * __builtin_dynamic_object_size: when the type of the flexible array member > + * 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) + 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), 16); > + EXPECT(__builtin_dynamic_object_size((char *)(bar + 2), 1), 8); > +} > + > +int main(int argc, char *argv[]) > +{ > + struct info *p = setup(); > + report(p); > + return 0; > +} > diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc > index 8de264d1dee2..4c1fa9b555fa 100644 > --- a/gcc/tree-object-size.cc > +++ b/gcc/tree-object-size.cc > @@ -762,9 +762,11 @@ addr_object_size (struct object_size_info *osi, > const_tree ptr, > 1: the number of the elements of the object type; > 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. > > - The size of the element can be retrived from the result type of the call, > - which is the pointer to the array 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. */ > static tree > access_with_size_object_size (const gcall *call, int object_size_type) > { > @@ -773,10 +775,12 @@ access_with_size_object_size (const gcall *call, int > object_size_type) > return size_unknown (object_size_type); > > gcc_assert (gimple_call_internal_p (call, IFN_ACCESS_WITH_SIZE)); > - /* Result type is a pointer type to the original flexible array type. */ > - tree result_type = gimple_call_return_type (call); > - gcc_assert (POINTER_TYPE_P (result_type)); > - tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (result_type))); > + /* The type of the 6th argument type is the pointer TYPE to the original > + flexible array 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)); > + tree element_size = TYPE_SIZE_UNIT (element_type); > tree ref_to_size = gimple_call_arg (call, 1); > unsigned int class_of_size = TREE_INT_CST_LOW (gimple_call_arg (call, 2)); > tree type = TREE_TYPE (gimple_call_arg (call, 3)); > -- > 2.31.1 >