]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Extend the attribute "counted_by" to support VOID pointer under GNU extension.
authorQing Zhao <qing.zhao@oracle.com>
Fri, 24 Oct 2025 18:02:06 +0000 (18:02 +0000)
committerQing Zhao <qing.zhao@oracle.com>
Thu, 30 Oct 2025 15:41:09 +0000 (15:41 +0000)
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/20251021095447.GL3245006@noisy.programming.kicks-ass.net/
for the initial request for this feature.

The attribute is allowed for a pointer to void, However,
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.

gcc/c-family/ChangeLog:

* c-attribs.cc (handle_counted_by_attribute): Allow counted_by for
void pointer. 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.c: New test.
* gcc.dg/pointer-counted-by-4-void.c: New test.

gcc/c-family/c-attribs.cc
gcc/c/c-typeck.cc
gcc/doc/extend.texi
gcc/testsuite/gcc.dg/pointer-counted-by-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pointer-counted-by-4-void.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pointer-counted-by.c

index 8ca767abbebaae241858b639b605157bcbef675e..28a034f6c065bc7ae73038e17339446f1caae5e4 100644 (file)
@@ -2963,14 +2963,16 @@ 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 can be applied to a pointer to void type, but issue
+     warning when -Wpointer-arith is presenting.  */
   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 (warn_pointer_arith)
+       warning_at (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
index 371583bd64ed8e6af1aa88d6c980b6f8227c1737..bc0fb6b59e556522289b2eed89a3479a64321df9 100644 (file)
@@ -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),
index 882c0820a6e648d21ff79847fb097f8dc339a576..8aaedaeb3b30077d79d2a5503d76c312969e485d 100644 (file)
@@ -7311,11 +7311,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}.  However,
+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.c b/gcc/testsuite/gcc.dg/pointer-counted-by-10.c
new file mode 100644 (file)
index 0000000..e2bd018
--- /dev/null
@@ -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 {
+  int count;
+  void *array __attribute__ ((counted_by (count))); /* { dg-warning "attribute is used for a pointer to void" } */
+}; 
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 (file)
index 0000000..71bac95
--- /dev/null
@@ -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"
index 0f18828ac113dce61de03e80449e738e340ee7b3..5e9ebef4ce5bc43eba07d1e505598109acca6bee 100644 (file)
@@ -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 {