summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2022-12-16 13:46:58 +0100
committerThomas Haller <thaller@redhat.com>2022-12-16 13:46:58 +0100
commit54c68e129014a5bb0ad7e8c301adce9569fb62c4 (patch)
treebd2022a4c69f22838d5e88010cc6a1a1918abcb7
parentcb275c5fefc924a67de90353eb87155241a29560 (diff)
downloadNetworkManager-54c68e129014a5bb0ad7e8c301adce9569fb62c4.tar.gz
Squashed 'src/c-stdaux/' changes from c37722ff2f55..eceefe959250
eceefe959250 doc: update README.md for typography df7e0ac7a792 build: release v1.3.0 293d76aded19 test-basic: use `non_constant_expr` 12f8380286f3 generic: handle compile time expression in _c_boolean_expr_(),_c_likely_()/_c_unlikely_() 92b25e384e3b test/basic: add tests for _c_boolean_expr_ 4c1765bc0b4d test/api: move _c_always_inline_ test to generic group fe95c7a78fe9 test/api: add missing test for _c_boolean_expr_ git-subtree-dir: src/c-stdaux git-subtree-split: eceefe9592501bce485db62966853b361e90ec2f
-rw-r--r--AUTHORS1
-rw-r--r--NEWS.md33
-rw-r--r--README.md12
-rw-r--r--meson.build2
-rw-r--r--src/c-stdaux-generic.h32
-rw-r--r--src/test-api.c17
-rw-r--r--src/test-basic.c65
7 files changed, 132 insertions, 30 deletions
diff --git a/AUTHORS b/AUTHORS
index 4b108f1901..0f2a73fd51 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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>
diff --git a/NEWS.md b/NEWS.md
index be824d664c..0cae9c5671 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -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
diff --git a/README.md b/README.md
index d56fbc05c5..985193c5fd 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/meson.build b/meson.build
index bf0da130fc..e41fd5f3e1 100644
--- a/meson.build
+++ b/meson.build
@@ -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'
diff --git a/src/c-stdaux-generic.h b/src/c-stdaux-generic.h
index 86be1d317a..4848617a79 100644
--- a/src/c-stdaux-generic.h
+++ b/src/c-stdaux-generic.h
@@ -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
diff --git a/src/test-api.c b/src/test-api.c
index b2f7ab1163..ca78c602d4 100644
--- a/src/test-api.c
+++ b/src/test-api.c
@@ -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;
diff --git a/src/test-basic.c b/src/test-basic.c
index 0cb656e0cf..ffb4bf6086 100644
--- a/src/test-basic.c
+++ b/src/test-basic.c
@@ -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;