mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 20:45:32 +00:00
c-stdaux: re-import git-subtree for 'src/c-stdaux'
git subtree pull --prefix src/c-stdaux git@github.com:c-util/c-stdaux.git main --squash
This commit is contained in:
commit
5e0b867a49
|
@ -35,6 +35,7 @@ COPYRIGHT: (ordered alphabetically)
|
|||
AUTHORS: (ordered alphabetically)
|
||||
David Rheinsberg <david.rheinsberg@gmail.com>
|
||||
Evgeny Vereshchagin <evvers@ya.ru>
|
||||
Jan Engelhardt <jengelh@inai.de>
|
||||
Lorenzo Arena <lorenzo.arena@powersoft.com>
|
||||
Michele Dionisio <michele.dionisio@gmail.com>
|
||||
Thomas Haller <thaller@redhat.com>
|
||||
|
|
|
@ -1,5 +1,38 @@
|
|||
# c-stdaux - Auxiliary macros and functions for the C standard library
|
||||
|
||||
## CHANGES WITH 1.3.0:
|
||||
|
||||
* Microsoft Windows is now supported as a target platform.
|
||||
|
||||
* The `C_COMPILER_*` and `C_OS_*` pre-processor constants now
|
||||
allow identifying the used compiler as well as the target OS.
|
||||
|
||||
* The new `_c_always_inline_` annotation allows telling compilers
|
||||
to inline a function unless technically not possible.
|
||||
|
||||
* Split c-stdaux.h into modules and include them from the root
|
||||
header for backwards compatibility. Inclusion of the new modules
|
||||
is guarded by the `C_COMPILER_*` and `C_OS_*` macros to prevent
|
||||
them from being used on unspported platforms. A direct include
|
||||
of the respective modules allows overriding that behavior.
|
||||
|
||||
The new modules provide the same functionality as before on the
|
||||
previously supported linux platforms. With the support of other
|
||||
platforms, individual modules might not be available, or generic
|
||||
functions might provide a stub that provides the same runtime
|
||||
behavior, but possibly with fewer diagnostics.
|
||||
|
||||
* Rework `c_assert()` to avoid context-expressions and instead use
|
||||
the ternary-operator to check for the assertion.
|
||||
|
||||
* Improve `c_{un,}likely()` to support constant-folding as well as
|
||||
-Wparantheses diagnostics if supported by the compiler. This adds
|
||||
`_c_boolean_expr_()` as a helper to achieve this.
|
||||
|
||||
Contributions from: David Rheinsberg, Thomas Haller
|
||||
|
||||
- Dußlingen, 2022-12-15
|
||||
|
||||
## CHANGES WITH 1.2.0:
|
||||
|
||||
* Add c_memcmp() as a safe wrapper around memcmp(3) that supports
|
||||
|
|
|
@ -3,10 +3,10 @@ c-stdaux
|
|||
|
||||
Auxiliary macros and functions for the C standard library
|
||||
|
||||
The c-stdaux project contains support-macros and auxiliary functions around the
|
||||
The c-stdaux project contains support macros and auxiliary functions around the
|
||||
functionality of common C standard libraries. This includes helpers for the
|
||||
ISO-C Standard Library, but also other common specifications like POSIX or
|
||||
common extended features of wide-spread compilers like gcc and clang.
|
||||
ISO C Standard Library, but also other common specifications like POSIX or
|
||||
common extended features of widespread compilers like gcc and clang.
|
||||
|
||||
### Project
|
||||
|
||||
|
@ -20,15 +20,15 @@ The requirements for this project are:
|
|||
|
||||
* `libc` (e.g., `glibc >= 2.16`)
|
||||
|
||||
At build-time, the following software is required:
|
||||
At build time, the following software is required:
|
||||
|
||||
* `meson >= 0.60`
|
||||
* `pkg-config >= 0.29`
|
||||
|
||||
### Build
|
||||
|
||||
The meson build-system is used for this project. Contact upstream
|
||||
documentation for detailed help. In most situations the following
|
||||
The meson build system is used for this project. Contact upstream
|
||||
documentation for detailed help. In most situations, the following
|
||||
commands are sufficient to build and install from source:
|
||||
|
||||
```sh
|
||||
|
|
|
@ -10,7 +10,7 @@ project(
|
|||
],
|
||||
license: 'Apache',
|
||||
meson_version: '>=0.60.0',
|
||||
version: '1.2.0',
|
||||
version: '1.3.0',
|
||||
)
|
||||
major = meson.project_version().split('.')[0]
|
||||
project_description = 'Auxiliary macros and functions for the C standard library'
|
||||
|
|
|
@ -132,24 +132,28 @@ extern "C" {
|
|||
* Return: Evaluates to the value of ``!!_x``.
|
||||
*/
|
||||
#define _c_boolean_expr_(_x) _c_internal_boolean_expr_(__COUNTER__, _x)
|
||||
#if defined(C_COMPILER_GNUC)
|
||||
#if defined(C_COMPILER_GNUC) && __GNUC__ > 4
|
||||
# define _c_internal_boolean_expr_(_uniq, _x) \
|
||||
__extension__ ({ \
|
||||
int C_VAR(b, _uniq); \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_constant_p(_x), \
|
||||
(!!(_x)), \
|
||||
(__extension__ ({ \
|
||||
int C_VAR(b, _uniq); \
|
||||
\
|
||||
/* \
|
||||
* Avoid any extra parentheses around the evaluation of `_x` to \
|
||||
* allow `-Wparentheses` to warn about use of `x = ...` and \
|
||||
* instead suggest `(x = ...)` or `x == ...`. \
|
||||
*/ \
|
||||
/* \
|
||||
* Avoid any extra parentheses around the evaluation of \
|
||||
* `_x` to allow `-Wparentheses` to warn about use of \
|
||||
* `x = ...` and instead suggest `(x = ...)` or \
|
||||
* `x == ...`. \
|
||||
*/ \
|
||||
\
|
||||
if (_x) \
|
||||
C_VAR(b, _uniq) = 1; \
|
||||
else \
|
||||
C_VAR(b, _uniq) = 0; \
|
||||
if (_x) \
|
||||
C_VAR(b, _uniq) = 1; \
|
||||
else \
|
||||
C_VAR(b, _uniq) = 0; \
|
||||
\
|
||||
C_VAR(b, _uniq); \
|
||||
})
|
||||
C_VAR(b, _uniq); \
|
||||
})))
|
||||
#else
|
||||
# define _c_internal_boolean_expr_(_uniq, _x) (!!(_x))
|
||||
#endif
|
||||
|
@ -299,7 +303,7 @@ extern "C" {
|
|||
* optimize it away.
|
||||
*/
|
||||
#define c_assert(_x) ( \
|
||||
(bool)(_x) \
|
||||
_c_likely_(_x) \
|
||||
? assert(true && #_x) \
|
||||
: assert(false && #_x) \
|
||||
)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#if defined(C_MODULE_GENERIC)
|
||||
|
||||
static inline _c_always_inline_ int always_inline_fn(void) { return 0; }
|
||||
_c_public_ int c_internal_public_fn(void);
|
||||
_c_public_ int c_internal_public_fn(void) { return 0; }
|
||||
|
||||
|
@ -46,6 +47,16 @@ static void test_api_generic(void) {
|
|||
#endif
|
||||
}
|
||||
|
||||
/* _c_always_inline_ */
|
||||
{
|
||||
c_assert(!always_inline_fn());
|
||||
}
|
||||
|
||||
/* _c_boolean_expr_ */
|
||||
{
|
||||
c_assert(_c_boolean_expr_(true));
|
||||
}
|
||||
|
||||
/* _c_likely_ */
|
||||
{
|
||||
c_assert(_c_likely_(true));
|
||||
|
@ -128,7 +139,6 @@ static void test_api_generic(void) {
|
|||
|
||||
#if defined(C_MODULE_GNUC)
|
||||
|
||||
static inline _c_always_inline_ int always_inline_fn(void) { return 0; }
|
||||
static _c_const_ int const_fn(void) { return 0; }
|
||||
static _c_deprecated_ _c_unused_ int deprecated_fn(void) { return 0; }
|
||||
_c_hidden_ int c_internal_hidden_fn(void);
|
||||
|
@ -139,11 +149,6 @@ static _c_sentinel_ int sentinel_fn(const _c_unused_ char *f, ...) { return 0; }
|
|||
static _c_unused_ int unused_fn(void) { return 0; }
|
||||
|
||||
static void test_api_gnuc(void) {
|
||||
/* _c_always_inline_ */
|
||||
{
|
||||
c_assert(!always_inline_fn());
|
||||
}
|
||||
|
||||
/* _c_cleanup_ */
|
||||
{
|
||||
_c_cleanup_(c_freep) void *foo = NULL;
|
||||
|
|
|
@ -11,7 +11,57 @@
|
|||
|
||||
#if defined(C_MODULE_GENERIC)
|
||||
|
||||
static void test_basic_generic(void) {
|
||||
static int check_cassert_unreachable(int switch_val) {
|
||||
int result;
|
||||
|
||||
/* Check whether this triggers a "-Wsometimes-uninitialized" warning or
|
||||
* whether the compiler recognizes c_assert(0) as unreachable code. */
|
||||
switch (switch_val) {
|
||||
case 1: result = 1; break;
|
||||
case 2: result = 2; break;
|
||||
default: c_assert(0);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void test_basic_generic(int non_constant_expr) {
|
||||
/*
|
||||
* Verify `_c_boolean_expr_` evaluates expressions to a boolean value
|
||||
* and correctly works on all platforms.
|
||||
*/
|
||||
{
|
||||
int v = 0;
|
||||
|
||||
c_assert(_c_boolean_expr_(0) == 0);
|
||||
c_assert(_c_boolean_expr_(1) == 1);
|
||||
c_assert(_c_boolean_expr_(2) == 1);
|
||||
c_assert(_c_boolean_expr_(INT_MIN) == 1);
|
||||
c_assert(_c_boolean_expr_(INT_MAX) == 1);
|
||||
|
||||
/* verify no double-evaluation takes place */
|
||||
c_assert(_c_boolean_expr_(v++) == 0);
|
||||
c_assert(_c_boolean_expr_(v) == 1);
|
||||
|
||||
#if defined(C_COMPILER_GNUC)
|
||||
c_assert(__builtin_constant_p(_c_boolean_expr_(1)));
|
||||
c_assert(!__builtin_constant_p(_c_boolean_expr_(non_constant_expr)));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that _c_likely_() and _c_unlikely_() can deal with constant
|
||||
* expressions.
|
||||
*/
|
||||
{
|
||||
#if defined(C_COMPILER_GNUC)
|
||||
c_assert(__builtin_constant_p(_c_likely_(1)));
|
||||
c_assert(__builtin_constant_p(_c_unlikely_(1)));
|
||||
c_assert(!__builtin_constant_p(_c_likely_(non_constant_expr)));
|
||||
c_assert(!__builtin_constant_p(_c_unlikely_(non_constant_expr)));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Test stringify/concatenation helpers. Also make sure to test that
|
||||
* the passed arguments are evaluated first, before they're stringified
|
||||
|
@ -184,6 +234,14 @@ static void test_basic_generic(void) {
|
|||
c_assert(++v2);
|
||||
if (v2 != 1)
|
||||
abort();
|
||||
|
||||
/*
|
||||
* Use the `check_cassert_unreachable()` helper to verify the
|
||||
* compiler does not complain about unreachable code when
|
||||
* `c_assert(0)` is used.
|
||||
*/
|
||||
c_assert(check_cassert_unreachable(1) == 1);
|
||||
c_assert(check_cassert_unreachable(2) == 2);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -267,7 +325,8 @@ static void test_basic_generic(void) {
|
|||
|
||||
#else /* C_MODULE_GENERIC */
|
||||
|
||||
static void test_basic_generic(void) {
|
||||
static void test_basic_generic(int non_constant_expr) {
|
||||
(void)non_constant_expr;
|
||||
}
|
||||
|
||||
#endif /* C_MODULE_GENERIC */
|
||||
|
@ -531,7 +590,7 @@ static void test_basic_unix(void) {
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
(void)argv;
|
||||
test_basic_generic();
|
||||
test_basic_generic(argc);
|
||||
test_basic_gnuc(argc);
|
||||
test_basic_unix();
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue