Bruno Haible <[email protected]> writes: >> 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. > > The way you are writing this, it sounds like the desire for perfection > won over the desire for simplicity. But look: GCC 10 is 6 years old. It is > carried by distributions such as > Debian 11, Ubuntu 20.10, Fedora 32, openSUSE 15.2, NetBSD 10. > When it comes to avoiding compilation errors, we need to consider this > compiler version, of course. But for warnings? Most package maintainers > use a distro that is not older than 3 years. Even RHEL 9 comes with GCC 11. > > So, I wouldn't make this an argument against the single ATTRIBUTE_ACCESS > macro. > > But for the user, your new 4 macros are easier to use than a single > ATTRIBUTE_ACCESS macro; therefore I would stick with them.
Yes, good point. I agree that my focus was probably in the wrong place. At least to me, this looks a bit awkward: ATTRIBUTE_ACCESS ((none, 1)) When compared to this: ATTRIBUTE_ACCESS_NONE ((1)) >> I attached a proposed patch. > >> @@ -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. > > Alphabetically, _GL_ATTRIBUTE_ACCESS_* comes before _GL_ATTRIBUTE_ALIGNED. > Therefore I would insert the new code before the 2 lines regarding > _GL_ATTRIBUTE_ALIGNED. Yep. >> +# 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))) > > Can you try to keep line lengths at <= 80 columns? I was going to because that was my preference as well, but I noticed some other lines were longer than 80 lines in that file, so I assumed you wouldn't like it. Some attributes can get quite long. Anyways, I adjusted that. > Regarding the comments: Is the "optional size S" measured in bytes or in > pointer > units? I.e. can the attribute be used e.g. on the wmemcpy function, whose > argument designates wchar_t elements, not bytes? The GCC docs don't state it, > therefore it would be good to state it here. It is mentioned a few paragraphs in: The optional size-index denotes the position of a function argument of integer type that specifies the maximum size of the access. The size is the number of elements of the type referenced by ref-index, or the number of bytes when the pointer type is void*. So, in that example you would use the number of wchar_t elements. But, it is worth documenting above the macro as well, to avoid forcing someone to spend time finding the correct section in the GCC manual. > Still regarding the comments: Add a few sentences that compare the access > attribute and the nonnull_if_nonzero attribute. Which relation do they have? > Is one stronger than the other? Does it make sense to use both at the same > place? Good points. The last paragraph in the GCC manual describing the attribute addresses that pretty well. Basically, the access attribute doesn't say whether or not the pointer can or cannot be NULL. If you wanted to specify that, you would need to use the nonnull or nonnull_if_nonzero attribute. Thanks for the detailed review, as always. I attached a v2 patch. I'll probably add them in a few places in Gnulib, if you don't mind. That way, we can make sure they are used, and to test them. I generally avoid making large changes, as you did when reducing variable scope, since I am (probably overly) paranoid about making typos. E.g., my additions of COUNTED_BY in coreutils have been fairly gradual. Collin
>From 247bc458f633ade18bbffe40521945b81edc2252 Mon Sep 17 00:00:00 2001 Message-ID: <247bc458f633ade18bbffe40521945b81edc2252.1794022848.git.collin.fu...@gmail.com> From: Collin Funk <[email protected]> Date: Thu, 5 Nov 2026 20:41:27 -0800 Subject: [PATCH v2] 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 | 29 ++++++++++++++++++++++++++- m4/gnulib-common.m4 | 48 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 211fa9e237..d4139ad755 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2026-11-06 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..0261e25072 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,31 @@ /* Applies to: functions. */ #define ATTRIBUTE_NONNULL_IF_NONZERO(np, ni) _GL_ATTRIBUTE_NONNULL_IF_NONZERO (np, ni) +/* _GL_ATTRIBUTE_ACCESS_READ_ONLY ((N, S)) declares that the Nth argument of + the function is used to read the referenced object but not to write to it. + _GL_ATTRIBUTE_ACCESS_WRITE_ONLY ((N, S)) declares that the Nth argument of + the function is used to write the referenced object but not to read from it. + _GL_ATTRIBUTE_ACCESS_READ_WRITE ((N, S)) declares that the Nth argument of + the function is used to both read from and write to the referenced object. + _GL_ATTRIBUTE_ACCESS_NONE ((N, S)) declares that the Nth argument of the + function is not used to access the referenced object at all. + + Each of the _GL_ATTRIBUTE_ACCESS_* macros accepts an optional size index S, + which specifies the position of the argument indicating the maximum size of + the access, in elements. The size of each element is determined by the type + of the Nth argument, or is 1 if that argument is a void pointer. The memory + pointed to by the sized object is not required to be initialized. These + macros specify how the object being pointed to can be accessed, not that the + access will happen. They also do not imply whether or not the pointer is or + can be NULL. This information can be specified by combining the + _GL_ATTRIBUTE_ACCESS_* macros with _GL_ATTRIBUTE_NONNULL or + _GL_ATTRIBUTE_NONNULL_IF_NONZERO. + */ +/* Applies to: functions. */ +#define ATTRIBUTE_ACCESS_READ_ONLY(args) _GL_ATTRIBUTE_ACCESS_READ_ONLY (args) +#define ATTRIBUTE_ACCESS_WRITE_ONLY(args) _GL_ATTRIBUTE_ACCESS_WRITE_ONLY (args) +#define ATTRIBUTE_ACCESS_READ_WRITE(args) _GL_ATTRIBUTE_ACCESS_READ_WRITE (args) +#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..119c638e66 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) @@ -355,6 +356,51 @@ AC_DEFUN([gl_COMMON_BODY] - In C, before the 'extern' keyword. - In C++, between the 'extern "C"' and the variable's type. */ + +/* _GL_ATTRIBUTE_ACCESS_READ_ONLY ((N, S)) declares that the Nth argument of + the function is used to read the referenced object but not to write to it. + _GL_ATTRIBUTE_ACCESS_WRITE_ONLY ((N, S)) declares that the Nth argument of + the function is used to write the referenced object but not to read from it. + _GL_ATTRIBUTE_ACCESS_READ_WRITE ((N, S)) declares that the Nth argument of + the function is used to both read from and write to the referenced object. + _GL_ATTRIBUTE_ACCESS_NONE ((N, S)) declares that the Nth argument of the + function is not used to access the referenced object at all. + + Each of the _GL_ATTRIBUTE_ACCESS_* macros accepts an optional size index S, + which specifies the position of the argument indicating the maximum size of + the access, in elements. The size of each element is determined by the type + of the Nth argument, or is 1 if that argument is a void pointer. The memory + pointed to by the sized object is not required to be initialized. These + macros specify how the object being pointed to can be accessed, not that the + access will happen. They also do not imply whether or not the pointer is or + can be NULL. This information can be specified by combining the + _GL_ATTRIBUTE_ACCESS_* macros with _GL_ATTRIBUTE_NONNULL or + _GL_ATTRIBUTE_NONNULL_IF_NONZERO. + */ +/* 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 + ]dnl There is no _GL_ATTRIBUTE_ALIGNED; use stdalign's alignas instead. [ /* _GL_ATTRIBUTE_ALLOC_SIZE ((N)) declares that the Nth argument of the function -- 2.56.0
