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 | ||