Project

General

Profile

Feature #769 ยป 0021-gnulib-common.m4-Update-to-serial-99.patch

Marko Lindqvist, 08/02/2024 12:07 AM

View differences:

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
    (1-1/1)