gcc/c/ChangeLog:

        * c-typeck.cc (build_counted_by_ref): Handle pointers with counted_by.
        (build_access_with_size_for_counted_by): Likewise.

gcc/ChangeLog:

        * tree-object-size.cc (access_with_size_object_size): Handle pointers
        with counted_by.
        (collect_object_sizes_for): Likewise.

gcc/testsuite/ChangeLog:

        * 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-8.c: New test.
---
 gcc/c/c-typeck.cc                           | 41 ++++++++------
 gcc/testsuite/gcc.dg/pointer-counted-by-4.c | 63 +++++++++++++++++++++
 gcc/testsuite/gcc.dg/pointer-counted-by-5.c | 48 ++++++++++++++++
 gcc/testsuite/gcc.dg/pointer-counted-by-6.c | 47 +++++++++++++++
 gcc/testsuite/gcc.dg/pointer-counted-by-7.c | 30 ++++++++++
 gcc/testsuite/gcc.dg/pointer-counted-by-8.c | 30 ++++++++++
 gcc/tree-object-size.cc                     | 11 +++-
 7 files changed, 251 insertions(+), 19 deletions(-)
 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
 create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-8.c

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index dbb688cabaa..9302236f126 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -2911,8 +2911,8 @@ should_suggest_deref_p (tree datum_type)
 
 /* For a SUBDATUM field of a structure or union DATUM, generate a REF to
    the object that represents its counted_by per the attribute counted_by
-   attached to this field if it's a flexible array member field, otherwise
-   return NULL_TREE.
+   attached to this field if it's a flexible array member or a pointer
+   field, otherwise return NULL_TREE.
    Set COUNTED_BY_TYPE to the TYPE of the counted_by field.
    For example, if:
 
@@ -2933,7 +2933,9 @@ static tree
 build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type)
 {
   tree type = TREE_TYPE (datum);
-  if (!c_flexible_array_member_type_p (TREE_TYPE (subdatum)))
+  tree sub_type = TREE_TYPE (subdatum);
+  if (!c_flexible_array_member_type_p (sub_type)
+      && TREE_CODE (sub_type) != POINTER_TYPE)
     return NULL_TREE;
 
   tree attr_counted_by = lookup_attribute ("counted_by",
@@ -2964,8 +2966,11 @@ build_counted_by_ref (tree datum, tree subdatum, tree 
*counted_by_type)
 }
 
 /* Given a COMPONENT_REF REF with the location LOC, the corresponding
-   COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate an INDIRECT_REF
-   to a call to the internal function .ACCESS_WITH_SIZE.
+   COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate the corresponding
+   call to the internal function .ACCESS_WITH_SIZE.
+
+   Generate an INDIRECT_REF to a call to the internal function
+   .ACCESS_WITH_SIZE.
 
    REF
 
@@ -2975,17 +2980,15 @@ build_counted_by_ref (tree datum, tree subdatum, tree 
*counted_by_type)
                        (TYPE_OF_ARRAY *)0))
 
    NOTE: The return type of this function is the POINTER type pointing
-   to the original flexible array type.
-   Then the type of the INDIRECT_REF is the original flexible array type.
-
-   The type of the first argument of this function is a POINTER type
-   to the original flexible array type.
+   to the original flexible array type or the original pointer type.
+   Then the type of the INDIRECT_REF is the original flexible array type
+   or the original pointer 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 a constant 0 of the same TYPE as
+   the return type of the call.
 
   */
 static tree
@@ -2993,20 +2996,26 @@ build_access_with_size_for_counted_by (location_t loc, 
tree ref,
                                       tree counted_by_ref,
                                       tree counted_by_type)
 {
-  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.  */
+  gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref))
+             || TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE);
+  bool is_fam = c_flexible_array_member_type_p (TREE_TYPE (ref));
+  tree first_arg = is_fam ? array_to_pointer_conversion (loc, ref)
+                         : build_unary_op (loc, ADDR_EXPR, ref, false);
+
+  /* The result type of the call is a pointer to the original type
+     of the ref.  */
   tree result_type = c_build_pointer_type (TREE_TYPE (ref));
 
   tree call
     = build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE,
                                    result_type, 6,
-                                   array_to_pointer_conversion (loc, ref),
+                                   first_arg,
                                    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 (result_type, 0));
-  /* Wrap the call with an INDIRECT_REF with the flexible array type.  */
+  /* Wrap the call with an INDIRECT_REF with the original type of the ref.  */
   call = build1 (INDIRECT_REF, TREE_TYPE (ref), call);
   SET_EXPR_LOCATION (call, loc);
   return call;
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..8f64e443c4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4.c
@@ -0,0 +1,63 @@
+/* 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"
+
+struct pointer_array {
+  int b;
+  int *c;
+} *p_array;
+
+struct annotated {
+  int b;
+  int *c __attribute__ ((counted_by (b)));
+} *p_array_annotated;
+
+struct nested_annotated {
+  struct {
+    union {
+      int b;
+      float f; 
+    };
+    int n;
+  };
+  int *c __attribute__ ((counted_by (b)));
+} *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 = (int *) malloc (sizeof (int) * normal_count);
+  p_array->b = normal_count;
+
+  p_array_annotated
+    = (struct annotated *) malloc (sizeof (struct annotated));
+  p_array_annotated->c = (int *) malloc (sizeof (int) * 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 = (int *) malloc (sizeof (int) * 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 (int));
+    EXPECT(__builtin_dynamic_object_size(p_array_nested_annotated->c, 1),
+          p_array_nested_annotated->b * sizeof (int));
+}
+
+int main(int argc, char *argv[])
+{
+  setup (10,10);   
+  test ();
+  DONE ();
+}
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..b136bbc13fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-5.c
@@ -0,0 +1,48 @@
+/* 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 {
+  struct {
+    union {
+      int b;
+      float f; 
+    };
+    int n;
+  };
+  int *c __attribute__ ((counted_by (b)));
+} *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);
+}
+
+int main(int argc, char *argv[])
+{
+  setup (-10);   
+  test ();
+  DONE ();
+}
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..4a1baa41d9a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-6.c
@@ -0,0 +1,47 @@
+/* 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), 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/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/testsuite/gcc.dg/pointer-counted-by-8.c 
b/gcc/testsuite/gcc.dg/pointer-counted-by-8.c
new file mode 100644
index 00000000000..3802fa1351d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-8.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..1eef66bea4d 100644
--- a/gcc/tree-object-size.cc
+++ b/gcc/tree-object-size.cc
@@ -773,10 +773,11 @@ 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 +787,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 +1855,10 @@ 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);
+           else if (TREE_CODE (rhs) == MEM_REF
+                    && POINTER_TYPE_P (TREE_TYPE (rhs))
+                    && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
+             reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, 0));
             else
               expr_object_size (osi, var, rhs);
           }
-- 
2.31.1

Reply via email to