--- /dev/null
+/* Test the attribute counted_by for pointer field and its usage in
+ * __builtin_dynamic_object_size. */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+#define PTR_TYPE char
+#include "pointer-counted-by-4.c"
--- /dev/null
+/* Test the attribute counted_by for pointer field and its usage in
+ * __builtin_dynamic_object_size. */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+#define PTR_TYPE float
+#include "pointer-counted-by-4.c"
--- /dev/null
+/* Test the attribute counted_by for pointer field and its usage in
+ * __builtin_dynamic_object_size. */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+struct A {
+ int a;
+ char *b;
+};
+#define PTR_TYPE struct A
+#include "pointer-counted-by-4.c"
--- /dev/null
+/* Test the attribute counted_by for pointer field and its usage in
+ * __builtin_dynamic_object_size. */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+union A {
+ int a;
+ float b;
+};
+#define PTR_TYPE union A
+#include "pointer-counted-by-4.c"
--- /dev/null
+/* 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"
+#ifndef PTR_TYPE
+#define PTR_TYPE int
+#endif
+struct pointer_array {
+ int b;
+ PTR_TYPE *c;
+} *p_array;
+
+struct annotated {
+ PTR_TYPE *c __attribute__ ((counted_by (b)));
+ int b;
+} *p_array_annotated;
+
+struct nested_annotated {
+ PTR_TYPE *c __attribute__ ((counted_by (b)));
+ struct {
+ union {
+ int b;
+ float f;
+ };
+ int n;
+ };
+} *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 = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * normal_count);
+ p_array->b = normal_count;
+
+ p_array_annotated
+ = (struct annotated *) malloc (sizeof (struct annotated));
+ p_array_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * 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 = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * 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 (PTR_TYPE));
+ EXPECT(__builtin_dynamic_object_size(p_array_nested_annotated->c, 1),
+ p_array_nested_annotated->b * sizeof (PTR_TYPE));
+}
+
+void cleanup ()
+{
+ free (p_array->c);
+ free (p_array);
+ free (p_array_annotated->c);
+ free (p_array_annotated);
+ free (p_array_nested_annotated->c);
+ free (p_array_nested_annotated);
+}
+
+int main(int argc, char *argv[])
+{
+ setup (10,10);
+ test ();
+ DONE ();
+ cleanup ();
+ return 0;
+}
--- /dev/null
+/* 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 {
+ int *c __attribute__ ((counted_by (b)));
+ struct {
+ union {
+ int b;
+ float f;
+ };
+ int n;
+ };
+} *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);
+}
+
+void cleanup ()
+{
+ free (array_annotated);
+ free (array_nested_annotated);
+}
+
+int main(int argc, char *argv[])
+{
+ setup (-10);
+ test ();
+ DONE ();
+ cleanup ();
+ return 0;
+}
--- /dev/null
+/* 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),
+ sizeof (struct foo) * 2);
+ EXPECT(__builtin_dynamic_object_size((char *)(bar + 2), 1),
+ sizeof (struct foo));
+}
+
+void cleanup (struct info *p)
+{
+ free (p->data);
+ free (p);
+}
+
+int main(int argc, char *argv[])
+{
+ struct info *p = setup();
+ report(p);
+ cleanup (p);
+ return 0;
+}
--- /dev/null
+/* 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));
+ free (p);
+ free (x.c);
+ DONE ();
+}
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)
{
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));
if (TREE_CODE (rhs) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (rhs)))
reexamine = merge_object_sizes (osi, var, rhs);
+ /* Handle the following stmt #2 to propagate the size from the
+ stmt #1 to #3:
+ 1 _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B);
+ 2 _5 = *_1;
+ 3 _6 = __builtin_dynamic_object_size (_5, 1);
+ */
+ else if (TREE_CODE (rhs) == MEM_REF
+ && POINTER_TYPE_P (TREE_TYPE (rhs))
+ && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME
+ && integer_zerop (TREE_OPERAND (rhs, 1)))
+ reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, 0));
else
expr_object_size (osi, var, rhs);
}