Message ID | 20240329160703.4012941-6-qing.zhao@oracle.com |
---|---|
State | New |
Headers | show |
Series | New attribute "counted_by" to annotate bounds for C99 FAM(PR108896) | expand |
The C front-end changes in this patch are OK for GCC 15.
On 2024-03-29 12:07, Qing Zhao 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. > > 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. This version looks fine to me for stage 1, but I'm not a maintainer so you'll need an ack from one to commit. Thanks, Sid > --- > 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 f7b0e08459b0..05948f76039e 100644 > --- a/gcc/c/c-typeck.cc > +++ b/gcc/c/c-typeck.cc > @@ -2608,7 +2608,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. > @@ -2620,6 +2621,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, > @@ -2632,12 +2636,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));
Sid, Thanks a lot for your review. Richard, Could you please comment on this patch? Is the middle-end part Okay for stage 1? Thanks. Qing On Apr 10, 2024, at 17:48, Siddhesh Poyarekar <siddhesh@gotplt.org> wrote: On 2024-03-29 12:07, Qing Zhao 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. 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. This version looks fine to me for stage 1, but I'm not a maintainer so you'll need an ack from one to commit. Thanks, Sid --- 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 f7b0e08459b0..05948f76039e 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2608,7 +2608,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. @@ -2620,6 +2621,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, @@ -2632,12 +2636,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));
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index f7b0e08459b0..05948f76039e 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2608,7 +2608,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. @@ -2620,6 +2621,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, @@ -2632,12 +2636,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));