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.
This commit is contained in:
Thomas Haller 2023-07-28 11:38:33 +02:00
parent 3732f08319
commit f27bf0b9ea
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728

View file

@ -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) \