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