From: Lennart Poettering Date: Thu, 29 Jul 2021 16:39:09 +0000 (+0200) Subject: macro: relax CONST_MAX() type check a tiny bit X-Git-Tag: v250-rc1~885^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=addae96a1a1f010b5db12cbf8b78719658fcc23b;p=thirdparty%2Fsystemd.git macro: relax CONST_MAX() type check a tiny bit This checked for strict type compatibility so far, which mean CONST_MAX() couldn't be used on two differently signed integers, even though conceptually there's nothing wrong with allowing that here, as C correctly picks the larger type in the ternary op. hence, let's explicitly whitelist integer comparisons here, as long as the signedness matches. --- diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index 967518600d4..e9fb4d39380 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -70,12 +70,29 @@ UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \ }) -/* evaluates to (void) if _A or _B are not constant or of different types */ +#define IS_UNSIGNED_INTEGER_TYPE(type) \ + (__builtin_types_compatible_p(typeof(type), unsigned char) || \ + __builtin_types_compatible_p(typeof(type), unsigned short) || \ + __builtin_types_compatible_p(typeof(type), unsigned) || \ + __builtin_types_compatible_p(typeof(type), unsigned long) || \ + __builtin_types_compatible_p(typeof(type), unsigned long long)) + +#define IS_SIGNED_INTEGER_TYPE(type) \ + (__builtin_types_compatible_p(typeof(type), signed char) || \ + __builtin_types_compatible_p(typeof(type), signed short) || \ + __builtin_types_compatible_p(typeof(type), signed) || \ + __builtin_types_compatible_p(typeof(type), signed long) || \ + __builtin_types_compatible_p(typeof(type), signed long long)) + +/* Evaluates to (void) if _A or _B are not constant or of different types (being integers of different sizes + * is also OK as long as the signedness matches) */ #define CONST_MAX(_A, _B) \ (__builtin_choose_expr( \ __builtin_constant_p(_A) && \ __builtin_constant_p(_B) && \ - __builtin_types_compatible_p(typeof(_A), typeof(_B)), \ + (__builtin_types_compatible_p(typeof(_A), typeof(_B)) || \ + (IS_UNSIGNED_INTEGER_TYPE(_A) && IS_UNSIGNED_INTEGER_TYPE(_B)) || \ + (IS_SIGNED_INTEGER_TYPE(_A) && IS_SIGNED_INTEGER_TYPE(_B))), \ ((_A) > (_B)) ? (_A) : (_B), \ VOID_0))