This extension is requested by linux kernel to ease the adoption of counted_by
attribute into linux kernel.

Please refer to
https://lore.kernel.org/lkml/[email protected]/
for the initial request for this feature.

The attribute is allowed for a pointer to void under GNU extension.
Warnings will be issued for such cases when -Wpointer-arith is
specified. When this attribute is applied on a pointer to void, the
size of each element of this pointer array is treated as 1.

This patch has been bootstrapped and regression tested on both x86 and aarch64.

Okay for committing?

thanks.

Qing.

======================
gcc/c-family/ChangeLog:

        * c-attribs.cc (handle_counted_by_attribute): Allow counted_by for
        void pointer under GNU extension. Issue warnings when -Wpointer-arith
        is present.

gcc/c/ChangeLog:

        * c-typeck.cc (build_access_with_size_for_counted_by): When the element
        type is void, assign size one as the element_size.

gcc/ChangeLog:

        * doc/extend.texi: Clarification when the counted_by attribute is 
applied
        on a void pointer.

gcc/testsuite/ChangeLog:

        * gcc.dg/pointer-counted-by.c: Update for void pointers.
        * gcc.dg/pointer-counted-by-10-b.c: New test.
        * gcc.dg/pointer-counted-by-10-c.c: New test.
        * gcc.dg/pointer-counted-by-10.c: New test.
        * gcc.dg/pointer-counted-by-4-void.c: New test.
---
 gcc/c-family/c-attribs.cc                     | 20 ++++++++++++++-----
 gcc/c/c-typeck.cc                             |  5 ++++-
 gcc/doc/extend.texi                           | 15 +++++++++-----
 .../gcc.dg/pointer-counted-by-10-b.c          |  8 ++++++++
 .../gcc.dg/pointer-counted-by-10-c.c          |  8 ++++++++
 gcc/testsuite/gcc.dg/pointer-counted-by-10.c  |  8 ++++++++
 .../gcc.dg/pointer-counted-by-4-void.c        |  6 ++++++
 gcc/testsuite/gcc.dg/pointer-counted-by.c     |  3 ++-
 8 files changed, 61 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-10-b.c
 create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-10-c.c
 create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-10.c
 create mode 100644 gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 8ca767abbeb..c32645505ab 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -2963,14 +2963,24 @@ handle_counted_by_attribute (tree *node, tree name,
                " array member field", name);
       *no_add_attrs = true;
     }
-  /* This attribute cannot be applied to a pointer to void type.  */
+  /* This attribute cannot be applied to a pointer to void type when GNU
+     extension is not enabled.  */
   else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
           && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == VOID_TYPE)
     {
-      error_at (DECL_SOURCE_LOCATION (decl),
-               "%qE attribute is not allowed for a pointer to void",
-               name);
-      *no_add_attrs = true;
+      if (flag_iso)
+       {
+         error_at (DECL_SOURCE_LOCATION (decl),
+                   "%qE attribute is not allowed for a pointer to void"
+                   " when GNU extension is not enabled",
+                   name);
+         *no_add_attrs = true;
+       }
+      else if (warn_pointer_arith)
+         pedwarn (DECL_SOURCE_LOCATION (decl),
+                  OPT_Wpointer_arith,
+                  "%qE attribute is used for a pointer to void",
+                  name);
     }
   /* This attribute cannot be applied to a pointer to function type.  */
   else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 371583bd64e..bc0fb6b59e5 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -3179,7 +3179,10 @@ build_access_with_size_for_counted_by (location_t loc, 
tree ref,
   tree result_type = is_fam ? c_build_pointer_type (TREE_TYPE (ref))
                     : TREE_TYPE (ref);
 
-  tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
+  tree element_type = TREE_TYPE (TREE_TYPE (ref));
+  tree element_size = VOID_TYPE_P (element_type)
+                     ? build_one_cst (size_type_node)
+                     : TYPE_SIZE_UNIT (element_type);
 
   tree first_param = is_fam
                     ? c_fully_fold (array_to_pointer_conversion (loc, ref),
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 94b76b75565..ee3abd976e8 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -7312,11 +7312,16 @@ the attribute.
 When the field that represents the number of the elements is assigned a
 negative integer value, the compiler treats the value as zero.
 
-The @code{counted_by} attribute is not allowed for a pointer to @code{void},
-a pointer to function, or a pointer to a structure or union that includes
-a flexible array member.  However, it is allowed for a pointer to
-non-void incomplete structure or union types, as long as the type could
-be completed before the first reference to the pointer.
+The @code{counted_by} attribute is not allowed for a pointer to function,
+or a pointer to a structure or union that includes a flexible array member.
+However, it is allowed for a pointer to non-void incomplete structure
+or union types, as long as the type could be completed before the first
+reference to the pointer.
+
+The attribute is allowed for a pointer to @code{void} under GNU extension.
+Warnings will be issued for such cases when @option{-Wpointer-arith} is
+specified. When this attribute is applied on a pointer to @code{void}, the
+size of each element of this pointer array is treated as 1.
 
 An explicit @code{counted_by} annotation defines a relationship between
 two objects, @code{p->array} and @code{p->count}, and there are the
diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-10-b.c 
b/gcc/testsuite/gcc.dg/pointer-counted-by-10-b.c
new file mode 100644
index 00000000000..89b8ff4f7b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-10-b.c
@@ -0,0 +1,8 @@
+/* Testing the correct usage of attribute counted_by for pointer to void.  */
+/* { dg-do compile } */
+/* { dg-options "-O0 -Wpointer-arith" } */
+
+struct pointer_array_7 {
+  int count;
+  void *array_7 __attribute__ ((counted_by (count))); /* { dg-warning 
"attribute is used for a pointer to void" } */
+}; 
diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-10-c.c 
b/gcc/testsuite/gcc.dg/pointer-counted-by-10-c.c
new file mode 100644
index 00000000000..4e45c0e9500
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-10-c.c
@@ -0,0 +1,8 @@
+/* Testing the correct usage of attribute counted_by for pointer to void.  */
+/* { dg-do compile } */
+/* { dg-options "-O0 -pedantic-errors" } */
+
+struct pointer_array_7 {
+  int count;
+  void *array_7 __attribute__ ((counted_by (count))); /* { dg-error "attribute 
is used for a pointer to void" } */
+}; 
diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-10.c 
b/gcc/testsuite/gcc.dg/pointer-counted-by-10.c
new file mode 100644
index 00000000000..b37a039c4cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-10.c
@@ -0,0 +1,8 @@
+/* Testing the correct usage of attribute counted_by for pointer to void.  */
+/* { dg-do compile } */
+/* { dg-options "-O0 -std=c11" } */
+
+struct pointer_array {
+  int count;
+  void *array __attribute__ ((counted_by (count))); /* { dg-error "attribute 
is not allowed for a pointer to void when GNU extension is not enabled" } */
+}; 
diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c 
b/gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c
new file mode 100644
index 00000000000..71bac95dfb2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c
@@ -0,0 +1,6 @@
+/* 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 void 
+#include "pointer-counted-by-4.c"
diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by.c 
b/gcc/testsuite/gcc.dg/pointer-counted-by.c
index 0f18828ac11..5e9ebef4ce5 100644
--- a/gcc/testsuite/gcc.dg/pointer-counted-by.c
+++ b/gcc/testsuite/gcc.dg/pointer-counted-by.c
@@ -49,9 +49,10 @@ struct pointer_array_6 {
   int *array_6 __attribute__ ((counted_by (days)));
 }; 
 
+/* counted_by is allowed for pointer to void when GNU extension is enabled.  */
 struct pointer_array_7 {
   int count;
-  void *array_7 __attribute__ ((counted_by (count))); /* { dg-error "attribute 
is not allowed for a pointer to void" } */
+  void *array_7 __attribute__ ((counted_by (count)));
 }; 
 
 struct pointer_array_8 {
-- 
2.31.1

Reply via email to