Feature #769 ยป 0021-gnulib-common.m4-Update-to-serial-99.patch
dependencies/m4/gnulib-common.m4 | ||
---|---|---|
# gnulib-common.m4
|
||
# serial 95
|
||
# serial 99
|
||
dnl Copyright (C) 2007-2024 Free Software Foundation, Inc.
|
||
dnl This file is free software; the Free Software Foundation
|
||
dnl gives unlimited permission to copy and/or distribute it,
|
||
... | ... | |
# define _GL_HAVE___HAS_C_ATTRIBUTE 0
|
||
#endif
|
||
/* Attributes in bracket syntax [[...]] vs. attributes in __attribute__((...))
|
||
syntax, in function declarations. There are two problems here.
|
||
(Last tested with gcc/g++ 14 and clang/clang++ 18.)
|
||
1) We want that the _GL_ATTRIBUTE_* can be cumulated on the same declaration
|
||
in any order.
|
||
=========================== foo.c = foo.cc ===========================
|
||
__attribute__ ((__deprecated__)) [[__nodiscard__]] int bar1 (int);
|
||
[[__nodiscard__]] __attribute__ ((__deprecated__)) int bar2 (int);
|
||
======================================================================
|
||
This gives a syntax error
|
||
- in C mode with gcc, and
|
||
- in C++ mode with clang++ version < 16.
|
||
*/
|
||
/* Define if, in a function declaration, the attributes in bracket syntax
|
||
[[...]] must come before the attributes in __attribute__((...)) syntax.
|
||
If this is defined, it is best to avoid the bracket syntax, so that the
|
||
various _GL_ATTRIBUTE_* can be cumulated on the same declaration in any
|
||
order. */
|
||
#ifdef __cplusplus
|
||
# if defined __clang__
|
||
# if defined __clang__ && __clang_major__ < 16
|
||
# define _GL_BRACKET_BEFORE_ATTRIBUTE 1
|
||
# endif
|
||
#else
|
||
... | ... | |
# define _GL_BRACKET_BEFORE_ATTRIBUTE 1
|
||
# endif
|
||
#endif
|
||
/*
|
||
2) We want that the _GL_ATTRIBUTE_* can be placed in a declaration
|
||
- without 'extern', in C as well as in C++,
|
||
- with 'extern', in C,
|
||
- with 'extern "C"', in C++
|
||
in the same position. That is, we don't want to be forced to use a
|
||
macro which arranges for the attribute to come before 'extern' in
|
||
one case and after 'extern' in the other case, because such a macro
|
||
would make the source code of .h files pretty ugly.
|
||
=========================== foo.c = foo.cc ===========================
|
||
#ifdef __cplusplus
|
||
# define CC "C"
|
||
#else
|
||
# define CC
|
||
#endif
|
||
#define ND [[__nodiscard__]]
|
||
#define WUR __attribute__((__warn_unused_result__))
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
// gcc clang g++ clang++
|
||
ND int foo (int);
|
||
int ND foo (int); // warn error warn error
|
||
int foo ND (int);
|
||
int foo (int) ND; // warn error warn error
|
||
WUR int foo (int);
|
||
int WUR foo (int);
|
||
int fo1 WUR (int); // error error error error
|
||
int foo (int) WUR;
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
// gcc clang g++ clang++
|
||
ND extern CC int foo (int); // error error
|
||
extern CC ND int foo (int); // error error
|
||
extern CC int ND foo (int); // warn error warn error
|
||
extern CC int foo ND (int);
|
||
extern CC int foo (int) ND; // warn error warn error
|
||
WUR extern CC int foo (int); // warn
|
||
extern CC WUR int foo (int);
|
||
extern CC int WUR foo (int);
|
||
extern CC int foo WUR (int); // error error error error
|
||
extern CC int foo (int) WUR;
|
||
ND EXTERN_C_FUNC int foo (int); // error error
|
||
EXTERN_C_FUNC ND int foo (int);
|
||
EXTERN_C_FUNC int ND foo (int); // warn error warn error
|
||
EXTERN_C_FUNC int foo ND (int);
|
||
EXTERN_C_FUNC int foo (int) ND; // warn error warn error
|
||
WUR EXTERN_C_FUNC int foo (int); // warn
|
||
EXTERN_C_FUNC WUR int foo (int);
|
||
EXTERN_C_FUNC int WUR foo (int);
|
||
EXTERN_C_FUNC int fo2 WUR (int); // error error error error
|
||
EXTERN_C_FUNC int foo (int) WUR;
|
||
======================================================================
|
||
So, if we insist on using the 'extern' keyword ('extern CC' idiom):
|
||
* If _GL_ATTRIBUTE_* expands to bracket syntax [[...]]
|
||
in both C and C++, there is one available position:
|
||
- between the function name and the parameter list.
|
||
* If _GL_ATTRIBUTE_* expands to __attribute__((...)) syntax
|
||
in both C and C++, there are several available positions:
|
||
- before the return type,
|
||
- between return type and function name,
|
||
- at the end of the declaration.
|
||
* If _GL_ATTRIBUTE_* expands to bracket syntax [[...]] in C and to
|
||
__attribute__((...)) syntax in C++, there is no available position:
|
||
it would need to come before 'extern' in C but after 'extern "C"'
|
||
in C++.
|
||
* If _GL_ATTRIBUTE_* expands to __attribute__((...)) syntax in C and
|
||
to bracket syntax [[...]] in C++, there is one available position:
|
||
- before the return type.
|
||
Whereas, if we use the 'EXTERN_C_FUNC' idiom, which conditionally
|
||
omits the 'extern' keyword:
|
||
* If _GL_ATTRIBUTE_* expands to bracket syntax [[...]]
|
||
in both C and C++, there are two available positions:
|
||
- before the return type,
|
||
- between the function name and the parameter list.
|
||
* If _GL_ATTRIBUTE_* expands to __attribute__((...)) syntax
|
||
in both C and C++, there are several available positions:
|
||
- before the return type,
|
||
- between return type and function name,
|
||
- at the end of the declaration.
|
||
* If _GL_ATTRIBUTE_* expands to bracket syntax [[...]] in C and to
|
||
__attribute__((...)) syntax in C++, there is one available position:
|
||
- before the return type.
|
||
* If _GL_ATTRIBUTE_* expands to __attribute__((...)) syntax in C and
|
||
to bracket syntax [[...]] in C++, there is one available position:
|
||
- before the return type.
|
||
The best choice is therefore to use the 'EXTERN_C_FUNC' idiom and
|
||
put the attributes before the return type. This works regardless
|
||
to what the _GL_ATTRIBUTE_* macros expand.
|
||
*/
|
||
/* Attributes in bracket syntax [[...]] vs. attributes in __attribute__((...))
|
||
syntax, in static/inline function definitions.
|
||
There are similar constraints as for function declarations. However, here,
|
||
we cannot omit the storage-class specifier. Therefore, the following rule
|
||
applies:
|
||
* The macros
|
||
_GL_ATTRIBUTE_CONST
|
||
_GL_ATTRIBUTE_DEPRECATED
|
||
_GL_ATTRIBUTE_MAYBE_UNUSED
|
||
_GL_ATTRIBUTE_NODISCARD
|
||
_GL_ATTRIBUTE_PURE
|
||
_GL_ATTRIBUTE_REPRODUCIBLE
|
||
_GL_ATTRIBUTE_UNSEQUENCED
|
||
which may expand to bracket syntax [[...]], must come first, before the
|
||
storage-class specifier.
|
||
* Other _GL_ATTRIBUTE_* macros, that expand to __attribute__((...)) syntax,
|
||
are better placed between the storage-class specifier and the return
|
||
type.
|
||
*/
|
||
/* Attributes in bracket syntax [[...]] vs. attributes in __attribute__((...))
|
||
syntax, in variable declarations.
|
||
At which position can they be placed?
|
||
(Last tested with gcc/g++ 14 and clang/clang++ 18.)
|
||
=========================== foo.c = foo.cc ===========================
|
||
#ifdef __cplusplus
|
||
# define CC "C"
|
||
#else
|
||
# define CC
|
||
#endif
|
||
#define BD [[__deprecated__]]
|
||
#define AD __attribute__ ((__deprecated__))
|
||
// gcc clang g++ clang++
|
||
BD extern CC int var; // error error
|
||
extern CC BD int var; // error error
|
||
extern CC int BD var; // warn error warn error
|
||
extern CC int var BD;
|
||
AD extern CC int var; // warn
|
||
extern CC AD int var;
|
||
extern CC int AD var;
|
||
extern CC int var AD;
|
||
BD extern CC int z[]; // error error
|
||
extern CC BD int z[]; // error error
|
||
extern CC int BD z[]; // warn error warn error
|
||
extern CC int z1 BD [];
|
||
extern CC int z[] BD; // warn error error
|
||
AD extern CC int z[]; // warn
|
||
extern CC AD int z[];
|
||
extern CC int AD z[];
|
||
extern CC int z2 AD []; // error error error error
|
||
extern CC int z[] AD;
|
||
======================================================================
|
||
* For non-array variables, the only good position is after the variable name,
|
||
that is, at the end of the declaration.
|
||
* For array variables, you will need to distinguish C and C++:
|
||
- In C, before the 'extern' keyword.
|
||
- In C++, between the 'extern "C"' and the variable's type.
|
||
*/
|
||
]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
|
||
... | ... | |
other attributes. */
|
||
#ifndef _GL_ATTRIBUTE_NOTHROW
|
||
# if defined __cplusplus
|
||
# if _GL_GNUC_PREREQ (2, 8) || __clang_major >= 4
|
||
# if _GL_GNUC_PREREQ (2, 8) || __clang_major__ >= 4
|
||
# if __cplusplus >= 201103L
|
||
# define _GL_ATTRIBUTE_NOTHROW noexcept (true)
|
||
# else
|