From f27bf0b9ea83186d5b8104bb48182b2000a62c28 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Fri, 28 Jul 2023 11:38:33 +0200 Subject: [PATCH] std-aux: add static-asserts about signedness of NM_MIN()/NM_MAX()/NM_CLAMP() The macros NM_MIN()/NM_MAX()/NM_CLAMP() use typeof() to accept any integer type as argument. Internally, they rely on standard C integral conversions of the <> operators and the ternary operator for evaluating the comparison and the result(type). That works mostly great. Except, comparing signed and unsigned values in C leads to oddities and the caller should explicitly take care of that. Add static assertions to check that the compared arguments have the same signedness. --- src/libnm-std-aux/nm-std-aux.h | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/libnm-std-aux/nm-std-aux.h b/src/libnm-std-aux/nm-std-aux.h index e65f2c417a..623a7c1e03 100644 --- a/src/libnm-std-aux/nm-std-aux.h +++ b/src/libnm-std-aux/nm-std-aux.h @@ -402,6 +402,9 @@ nm_mult_clamped_u(unsigned a, unsigned b) ({ \ typeof(a) NM_UNIQ_T(A, aq) = (a); \ typeof(b) NM_UNIQ_T(B, bq) = (b); \ + \ + G_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(NM_UNIQ_T(A, aq), NM_UNIQ_T(B, bq))); \ + \ ((NM_UNIQ_T(A, aq) < NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ }) @@ -410,19 +413,25 @@ nm_mult_clamped_u(unsigned a, unsigned b) ({ \ typeof(a) NM_UNIQ_T(A, aq) = (a); \ typeof(b) NM_UNIQ_T(B, bq) = (b); \ + \ + G_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(NM_UNIQ_T(A, aq), NM_UNIQ_T(B, bq))); \ + \ ((NM_UNIQ_T(A, aq) > NM_UNIQ_T(B, bq)) ? NM_UNIQ_T(A, aq) : NM_UNIQ_T(B, bq)); \ }) #define NM_CLAMP(x, low, high) __NM_CLAMP(NM_UNIQ, x, NM_UNIQ, low, NM_UNIQ, high) -#define __NM_CLAMP(xq, x, lowq, low, highq, high) \ - ({ \ - typeof(x) NM_UNIQ_T(X, xq) = (x); \ - typeof(low) NM_UNIQ_T(LOW, lowq) = (low); \ - typeof(high) NM_UNIQ_T(HIGH, highq) = (high); \ - \ - ((NM_UNIQ_T(X, xq) > NM_UNIQ_T(HIGH, highq)) ? NM_UNIQ_T(HIGH, highq) \ - : (NM_UNIQ_T(X, xq) < NM_UNIQ_T(LOW, lowq)) ? NM_UNIQ_T(LOW, lowq) \ - : NM_UNIQ_T(X, xq)); \ +#define __NM_CLAMP(xq, x, lowq, low, highq, high) \ + ({ \ + typeof(x) NM_UNIQ_T(X, xq) = (x); \ + typeof(low) NM_UNIQ_T(LOW, lowq) = (low); \ + typeof(high) NM_UNIQ_T(HIGH, highq) = (high); \ + \ + G_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(NM_UNIQ_T(X, xq), NM_UNIQ_T(LOW, lowq))); \ + G_STATIC_ASSERT(_NM_INT_SAME_SIGNEDNESS(NM_UNIQ_T(X, xq), NM_UNIQ_T(HIGH, highq))); \ + \ + ((NM_UNIQ_T(X, xq) > NM_UNIQ_T(HIGH, highq)) ? NM_UNIQ_T(HIGH, highq) \ + : (NM_UNIQ_T(X, xq) < NM_UNIQ_T(LOW, lowq)) ? NM_UNIQ_T(LOW, lowq) \ + : NM_UNIQ_T(X, xq)); \ }) #define NM_MAX_WITH_CMP(cmp, a, b) \