diff mbox series

[v8,5/5] Add the 6th argument to .ACCESS_WITH_SIZE

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

Commit Message

Qing Zhao March 29, 2024, 4:07 p.m. UTC
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.
---
 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

Comments

Joseph Myers April 10, 2024, 6:38 p.m. UTC | #1
The C front-end changes in this patch are OK for GCC 15.
Siddhesh Poyarekar April 10, 2024, 9:48 p.m. UTC | #2
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));
Qing Zhao April 11, 2024, 1:24 p.m. UTC | #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 mbox series

Patch

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));