https://gcc.gnu.org/g:1cf8d08a977f528c6e81601b7586ccf8bc8aa2a6

commit r16-2180-g1cf8d08a977f528c6e81601b7586ccf8bc8aa2a6
Author: Qing Zhao <qing.z...@oracle.com>
Date:   Wed Jul 9 20:10:30 2025 +0000

    Passing TYPE_SIZE_UNIT of the element as the 6th argument to 
.ACCESS_WITH_SIZE (PR121000)
    
    The size of the element of the FAM _cannot_ reliably depends on the original
    TYPE of the FAM that we passed as the 6th parameter to the 
.ACCESS_WITH_SIZE:
    
         TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (gimple_call_arg (call, 5))))
    
    when the element of the FAM has a variable length type. Since the variable
     that represents TYPE_SIZE_UNIT has no explicit usage in the original IL,
    compiler transformations (such as DSE) that are applied before object_size
    phase might eliminate the whole definition to the variable that represents
    the TYPE_SIZE_UNIT of the element of the FAM.
    
    In order to resolve this issue, instead of passing the original TYPE of the
    FAM as the 6th argument to .ACCESS_WITH_SIZE, we should explicitly pass the
    original TYPE_SIZE_UNIT of the element TYPE of the FAM as the 6th argument
    to the call to  .ACCESS_WITH_SIZE.
    
            PR middle-end/121000
    
    gcc/c/ChangeLog:
    
            * c-typeck.cc (build_access_with_size_for_counted_by): Update 
comments.
            Pass TYPE_SIZE_UNIT of the element as the 6th argument.
    
    gcc/ChangeLog:
    
            * internal-fn.cc (expand_ACCESS_WITH_SIZE): Update comments.
            * internal-fn.def (ACCESS_WITH_SIZE): Update comments.
            * tree-object-size.cc (access_with_size_object_size): Update 
comments.
            Get the element_size from the 6th argument directly.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/flex-array-counted-by-pr121000.c: New test.

Diff:
---
 gcc/c/c-typeck.cc                                  | 10 +++--
 gcc/internal-fn.cc                                 | 10 ++---
 gcc/internal-fn.def                                |  2 +-
 .../gcc.dg/flex-array-counted-by-pr121000.c        | 43 ++++++++++++++++++++++
 gcc/tree-object-size.cc                            | 28 +++++++-------
 5 files changed, 69 insertions(+), 24 deletions(-)

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index e24629be918b..de3d6c78db88 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -2983,7 +2983,7 @@ 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,
-                       (TYPE_OF_ARRAY *)0))
+                       TYPE_SIZE_UNIT for element)
 
    NOTE: The return type of this function is the POINTER type pointing
    to the original flexible array type.
@@ -2995,8 +2995,8 @@ 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.
+   The 6th argument of the call is the TYPE_SIZE_UNIT of the element TYPE
+   of the FAM.
 
   */
 static tree
@@ -3007,6 +3007,8 @@ build_access_with_size_for_counted_by (location_t loc, 
tree ref,
   gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)));
   /* The result type of the call is a pointer to the flexible array type.  */
   tree result_type = c_build_pointer_type (TREE_TYPE (ref));
+  tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
+
   tree first_param
     = c_fully_fold (array_to_pointer_conversion (loc, ref), false, NULL);
   tree second_param
@@ -3020,7 +3022,7 @@ build_access_with_size_for_counted_by (location_t loc, 
tree 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 (result_type, 0));
+                                   element_size);
   /* 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 ed6ef0e4c647..c6e705cb6f5e 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -3443,7 +3443,7 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
 
 /* Expand the IFN_ACCESS_WITH_SIZE function:
    ACCESS_WITH_SIZE (REF_TO_OBJ, REF_TO_SIZE, CLASS_OF_SIZE,
-                    TYPE_OF_SIZE, ACCESS_MODE)
+                    TYPE_OF_SIZE, ACCESS_MODE, TYPE_SIZE_UNIT for element)
    which returns the REF_TO_OBJ same as the 1st argument;
 
    1st argument REF_TO_OBJ: The reference to the object;
@@ -3451,16 +3451,16 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
    3rd argument CLASS_OF_SIZE: The size referenced by the REF_TO_SIZE 
represents
      0: the number of bytes.
      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
+   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
    5th argument ACCESS_MODE:
     -1: Unknown access semantics
      0: none
      1: read_only
      2: write_only
      3: read_write
-   6th argument: A constant 0 with the pointer TYPE to the original flexible
-     array type.
+   6th argument: The TYPE_SIZE_UNIT of the element TYPE of the FAM when the
+    3rd argument is 1; NULL when the 3rd argument is 0.
 
    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/internal-fn.def b/gcc/internal-fn.def
index 914ee9f278cd..95f462096a1e 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -525,7 +525,7 @@ DEF_INTERNAL_FN (DEFERRED_INIT, ECF_CONST | ECF_LEAF | 
ECF_NOTHROW, NULL)
 
 /* A function to associate the access size and access mode information
    with the corresponding reference to an object.  It only reads from the
-   2nd argument.  */
+   2nd and the 6th arguments.  */
 DEF_INTERNAL_FN (ACCESS_WITH_SIZE, ECF_PURE | ECF_LEAF | ECF_NOTHROW, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by-pr121000.c 
b/gcc/testsuite/gcc.dg/flex-array-counted-by-pr121000.c
new file mode 100644
index 000000000000..5b9a2c642d93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/flex-array-counted-by-pr121000.c
@@ -0,0 +1,43 @@
+/* PR middle-end/121000 */
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+#include "builtin-object-size-common.h"
+
+/* The parameter m must be const qualified to avoid the m is 
+   marked as TREE_SIDE_EFFECTS in IR.
+   The __builtin_dynamic_object_size will be folded as -1 by
+   fold_builtin_object_size when m is NOT const qualified.  */
+
+void
+foo (int n, const int m)
+{
+  typedef int A[m];
+  struct S { int n, m; A a[2]; A b[] __attribute__((counted_by (n))); } *p;
+  p = __builtin_malloc (sizeof (struct S) + sizeof (A) * n);
+  p->n = n;
+  p->m = m;
+  EXPECT (__builtin_dynamic_object_size (p->b, 1), sizeof (A) * n);
+}
+
+/* The parameter m1, m2 must be const qualified to avoid the m is 
+   marked as TREE_SIDE_EFFECTS in IR.
+   The __builtin_dynamic_object_size will be folded as -1 by
+   fold_builtin_object_size when m1 or m2 is NOT const qualified.  */
+void
+foo_1 (int n, const int m1, const int m2)
+{
+  typedef int A[m1][m2];
+  struct S { int n; A a[2]; A b[] __attribute__((counted_by (n))); } *p;
+  p = __builtin_malloc (sizeof (struct S) + sizeof (A) * n);
+  p->n = n;
+  EXPECT (__builtin_dynamic_object_size (p->b, 1), sizeof (A) * n);
+}
+
+int
+main ()
+{
+  foo (2, 10);
+  foo_1 (2, 10, 20);
+  return 0;
+}
diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc
index 2d13ab79a84a..77a3258ea6e5 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -851,38 +851,38 @@ addr_object_size (struct object_size_info *osi, 
const_tree ptr,
 
 /* Compute __builtin_object_size for a CALL to .ACCESS_WITH_SIZE,
    OBJECT_SIZE_TYPE is the second argument from __builtin_object_size.
-   The 2nd, 3rd, and the 4th parameters of the call determine the size of
+
+   The 2nd, 3rd, 4th and 6th parameters of the call determine the size of
    the CALL:
 
    2nd argument REF_TO_SIZE: The reference to the size of the object,
    3rd argument CLASS_OF_SIZE: The size referenced by the REF_TO_SIZE 
represents
      0: the number of bytes;
      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.
+   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:  The TYPE_SIZE_UNIT of the element TYPE of the FAM when the
+    3rd argument is 1; NULL when the 3rd argument is 0.  */
 
-   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)
 {
   /* If not for dynamic object size, return.  */
   if ((object_size_type & OST_DYNAMIC) == 0)
     return size_unknown (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.  */
-  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));
 
+  /* The 6th argument is the TYPE_SIZE_UNIT for the element of the original
+     flexible array.  */
+  tree element_size = gimple_call_arg (call, 5);
+
+  gcc_assert ((class_of_size == 1 && element_size)
+             || (class_of_size == 0 && !element_size));
+
   tree size = fold_build2 (MEM_REF, type, ref_to_size,
                           build_int_cst (ptr_type_node, 0));

Reply via email to