Most of the time, when testing GNU coreutils, I run a standard configure
command like this:

    $ ./configure

If I need to go into the debugger, I will just edit the Makefile by hand
to pretty much do the following:

    $ sed -i -e 's/-Werror//g' -e 's/-g -O2/-ggdb3 -O0/g' Makefile

In coreutils, this leads to the following warning every time src/cksum.c
is compiled, which is done for various programs, e.g., sha1sum,
sha256sum, cksum, etc.
    
    src/cksum.c: In function 'digest_check':
    src/cksum.c:1381:31: warning: 'bin_buffer_unaligned' may be used 
uninitialized [-Wmaybe-uninitialized]
     1381 |   unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, 
DIGEST_ALIGN);
          |                               
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In file included from src/cksum.c:25:
    src/system.h:510:1: note: by argument 1 of type 'const void *' to 
'ptr_align' declared here
      510 | ptr_align (void const *ptr, size_t alignment)
          | ^~~~~~~~~
    src/cksum.c:1379:17: note: 'bin_buffer_unaligned' declared here
     1379 |   unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + 
DIGEST_ALIGN];
          |                 ^~~~~~~~~~~~~~~~~~~~
    src/cksum.c: In function 'main':
    src/cksum.c:1576:31: warning: 'bin_buffer_unaligned' may be used 
uninitialized [-Wmaybe-uninitialized]
     1576 |   unsigned char *bin_buffer = ptr_align (bin_buffer_unaligned, 
DIGEST_ALIGN);
          |                               
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    src/system.h:510:1: note: by argument 1 of type 'const void *' to 
'ptr_align' declared here
      510 | ptr_align (void const *ptr, size_t alignment)
          | ^~~~~~~~~
    src/cksum.c:1574:17: note: 'bin_buffer_unaligned' declared here
     1574 |   unsigned char bin_buffer_unaligned[DIGEST_BIN_BYTES + 
DIGEST_ALIGN];
          |                 ^~~~~~~~~~~~~~~~~~~~
    
The warning isn't really meaningful since the function does not access
uninitialized memory. It simply returns an aligned pointer into the
buffer.

I was taking a look at GCC attributes to see what might be helpful for
coreutils, gnulib, etc., and I tested the access attribute on this. When
compiled with the following attribute, the warning is silenced:

    __attribute__ ((__access__ (__none__, 1)))
    static inline void *
    ptr_align (void const *ptr, size_t alignment)
    {
      char const *p0 = ptr;
      char const *p1 = p0 + alignment - 1;
      return (void *) (p1 - (size_t) p1 % alignment);
    }

The proposed patch isn’t intended just for the purposes of this warning,
which I am perfectly happy to continue ignoring as I have been. It is
just an example where I noticed it being beneficial. I suspect, and
certainly hope, that this attribute might lead to the compiler catching
more issues.

Note that the access attribute also allows you to provide a size
argument index to associate with a pointer. The GCC documentation
mentions that it is intended to help object size checking [1] [2].
Whether that is implemented yet, I am not sure.

While it would have been nice to provide a single ATTRIBUTE_ACCESS
macro, I decided to make them separate. This is because GCC 10.1.0 added
the read_only, read_write, and write_only options [3], and GCC 11.1.0
added the additional none option. I didn’t like the idea of dropping the
entire attribute for GCC 10.x, just because it doesn’t support one of
the access type arguments.

I attached a proposed patch. Here is what the earlier function would
look like using one of the newly added macros:

    ATTRIBUTE_ACCESS_NONE ((1))
    static inline void *
    ptr_align (void const *ptr, size_t alignment)
    {
      char const *p0 = ptr;
      char const *p1 = p0 + alignment - 1;
      return (void *) (p1 - (size_t) p1 % alignment);
    }

Thoughts?

Collin

[1] https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html
[2] https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html
[3] 
https://github.com/gcc-mirror/gcc/commit/54aa6b58fe2fe73bbe67e0485777e0c410a18673
[4] 
https://github.com/gcc-mirror/gcc/commit/b825a22890740f341eae566af27e18e528cd29a7

>From 54f519e77ad5b821c9c03e7896c12950c3b6599f Mon Sep 17 00:00:00 2001
Message-ID: <54f519e77ad5b821c9c03e7896c12950c3b6599f.1793941748.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Thu, 5 Nov 2026 20:41:27 -0800
Subject: [PATCH] attribute: Provide access to gcc's access attribute.

* m4/gnulib-common.m4 (gl_COMMON_BODY): Define
_GL_ATTRIBUTE_ACCESS_NONE, _GL_ATTRIBUTE_ACCESS_READ_ONLY,
_GL_ATTRIBUTE_ACCESS_READ_WRITE, and _GL_ATTRIBUTE_ACCESS_WRITE_ONLY.
* lib/attribute.h (ATTRIBUTE_ACCESS_NONE, ATTRIBUTE_ACCESS_READ_ONLY)
(ATTRIBUTE_ACCESS_READ_WRITE, ATTRIBUTE_ACCESS_WRITE_ONLY): New macros.
---
 ChangeLog           |  9 +++++++++
 lib/attribute.h     | 27 ++++++++++++++++++++++++++-
 m4/gnulib-common.m4 | 30 +++++++++++++++++++++++++++++-
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 211fa9e237..96f9c2e5a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2026-11-05  Collin Funk  <[email protected]>
+
+	attribute: Provide access to gcc's access attribute.
+	* m4/gnulib-common.m4 (gl_COMMON_BODY): Define
+	_GL_ATTRIBUTE_ACCESS_NONE, _GL_ATTRIBUTE_ACCESS_READ_ONLY,
+	_GL_ATTRIBUTE_ACCESS_READ_WRITE, and _GL_ATTRIBUTE_ACCESS_WRITE_ONLY.
+	* lib/attribute.h (ATTRIBUTE_ACCESS_NONE, ATTRIBUTE_ACCESS_READ_ONLY)
+	(ATTRIBUTE_ACCESS_READ_WRITE, ATTRIBUTE_ACCESS_WRITE_ONLY): New macros.
+
 2026-11-05  Bruno Haible  <[email protected]>
 
 	strtof, strtod, strtold: Fix sign of NaN results.
diff --git a/lib/attribute.h b/lib/attribute.h
index 10de47516f..365d7bd27e 100644
--- a/lib/attribute.h
+++ b/lib/attribute.h
@@ -79,7 +79,9 @@
      These names begin with 'ATTRIBUTE_' to avoid name clashes.  */
 
 
-/* This file uses _GL_ATTRIBUTE_ALLOC_SIZE, _GL_ATTRIBUTE_ALWAYS_INLINE,
+/* This file uses _GL_ATTRIBUTE_ACCESS_NONE, _GL_ATTRIBUTE_ACCESS_READ_ONLY,
+   _GL_ATTRIBUTE_ACCESS_READ_WRITE, _GL_ATTRIBUTE_ACCESS_WRITE_ONLY,
+   _GL_ATTRIBUTE_ALLOC_SIZE, _GL_ATTRIBUTE_ALWAYS_INLINE,
    _GL_ATTRIBUTE_ARTIFICIAL, _GL_ATTRIBUTE_COLD, _GL_ATTRIBUTE_CONST,
    _GL_ATTRIBUTE_COUNTED_BY, _GL_ATTRIBUTE_DEALLOC, _GL_ATTRIBUTE_DEPRECATED,
    _GL_ATTRIBUTE_ERROR, _GL_ATTRIBUTE_WARNING, _GL_ATTRIBUTE_EXTERNALLY_VISIBLE,
@@ -176,6 +178,29 @@
 /* Applies to: functions.  */
 #define ATTRIBUTE_NONNULL_IF_NONZERO(np, ni) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (np, ni)
 
+/* ATTRIBUTE_ACCESS_READ_ONLY ((N, S)) declares that the argument N of
+   optional size S is used to read the referenced object but not
+   write to it.  */
+/* Applies to: functions.  */
+#define ATTRIBUTE_ACCESS_READ_ONLY(args) _GL_ATTRIBUTE_ACCESS_READ_ONLY(args)
+
+/* ATTRIBUTE_ACCESS_WRITE_ONLY ((N, S)) declares that the argument N of
+   optional size S is used to write the referenced object but not read
+   from it.  */
+/* Applies to: functions.  */
+#define ATTRIBUTE_ACCESS_WRITE_ONLY(args) _GL_ATTRIBUTE_ACCESS_WRITE_ONLY(args)
+
+/* ATTRIBUTE_ACCESS_READ_WRITE ((N, S)) declares that the argument N of
+   optional size S is used to both read and write from the referenced
+   object.  */
+/* Applies to: functions.  */
+#define ATTRIBUTE_ACCESS_READ_WRITE(args) _GL_ATTRIBUTE_ACCESS_READ_WRITE(args)
+
+/* ATTRIBUTE_ACCESS_NONE ((N, S)) declares that the argument N of
+   optional size S is not used to access the referenced object at all.  */
+/* Applies to: functions.  */
+#define ATTRIBUTE_ACCESS_NONE(args) _GL_ATTRIBUTE_ACCESS_NONE(args)
+
 
 /* The function's return value is a non-NULL pointer.  */
 /* Applies to: functions.  */
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index a1d0f0d26d..527297a89b 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -1,5 +1,5 @@
 # gnulib-common.m4
-# serial 125
+# serial 126
 dnl Copyright (C) 2007-2026 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -112,6 +112,7 @@ AC_DEFUN([gl_COMMON_BODY]
 /* The following lines list the first GCC version that supports the attribute.
    Although the lines are not used in GCC 5 and later (as GCC 5 introduced
    __has_attribute support), list GCC versions 5+ anyway for completeness.  */
+#  define _GL_ATTR_access _GL_GNUC_PREREQ (10, 1)
 #  define _GL_ATTR_alloc_size _GL_GNUC_PREREQ (4, 3)
 #  define _GL_ATTR_always_inline _GL_GNUC_PREREQ (3, 2)
 #  define _GL_ATTR_artificial _GL_GNUC_PREREQ (4, 3)
@@ -357,6 +358,33 @@ AC_DEFUN([gl_COMMON_BODY]
  */
 ]dnl There is no _GL_ATTRIBUTE_ALIGNED; use stdalign's alignas instead.
 [
+/* _GL_ATTRIBUTE_ACCESS_READ_ONLY ((N, S)) declares that the argument N of
+   optional size S is used to read the referenced object but not write to it.
+   _GL_ATTRIBUTE_ACCESS_WRITE_ONLY ((N, S)) declares that the argument N of
+   optional size S is used to write the referenced object but not read from it.
+   _GL_ATTRIBUTE_ACCESS_READ_WRITE ((N, S)) declares that the argument N of
+   optional size S is used to both read and write from the referenced object.
+   _GL_ATTRIBUTE_ACCESS_NONE ((N, S)) declares that the argument N of
+   optional size S is not used to access the referenced object at all.  */
+/* Applies to: functions.  */
+/* Clang does not support these attributes.  */
+#ifndef _GL_ATTRIBUTE_ACCESS_READ_ONLY
+# if _GL_HAS_ATTRIBUTE (access) && ! defined __clang__
+#  define _GL_ATTRIBUTE_ACCESS_READ_ONLY(args) __attribute__ ((__access__ (__read_only__, args)))
+#  define _GL_ATTRIBUTE_ACCESS_WRITE_ONLY(args) __attribute__ ((__access__ (__write_only__, args)))
+#  define _GL_ATTRIBUTE_ACCESS_READ_WRITE(args) __attribute__ ((__access__ (__read_write__, args)))
+#  if _GL_GNUC_PREREQ (11, 1)
+#   define _GL_ATTRIBUTE_ACCESS_NONE(args) __attribute__ ((__access__ (__none__, args)))
+#  else
+#   define _GL_ATTRIBUTE_ACCESS_NONE(args)
+#  endif
+# else
+#  define _GL_ATTRIBUTE_ACCESS_READ_ONLY(args)
+#  define _GL_ATTRIBUTE_ACCESS_WRITE_ONLY(args)
+#  define _GL_ATTRIBUTE_ACCESS_READ_WRITE(args)
+#  define _GL_ATTRIBUTE_ACCESS_NONE(args)
+# endif
+#endif
 /* _GL_ATTRIBUTE_ALLOC_SIZE ((N)) declares that the Nth argument of the function
    is the size of the returned memory block.
    _GL_ATTRIBUTE_ALLOC_SIZE ((M, N)) declares that the Mth argument multiplied
-- 
2.56.0

Reply via email to