basic/macro: make CONST_MAX(DECIMAL_STR_MAX(…), STRLEN(…)) possible

When those two macros were used together in CONST_MAX(), gcc would complain
about a type mismatch. So either DECIMAL_STR_MAX() should be made size_t like
STRLEN(), or STRLEN() be made unsigned.

Since those macros are only usable on arguments of (small) fixed size, any type
should be fine (even char would work…). For buffer size specifications, both
size_t and unsigned are OK. But unsigned was used for DECIMAL_STR_MAX macros
and FORMAT_foo_MAX macros, making STRLEN the only exception, so let's adjust
STRLEN() to be unsigned too.

Also: I don't think this is currently used anywhere, but if any of those macros
were used as an argument to sprintf, size_t would require a cast. ("%*s"
requires an int/unsigned argument.)
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-07-06 09:49:56 +02:00
parent 22fd4a8f85
commit d3e4029457
2 changed files with 14 additions and 5 deletions

View File

@@ -213,7 +213,7 @@ static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
* Contrary to strlen(), this is a constant expression.
* @x: a string literal.
*/
#define STRLEN(x) (sizeof(""x"") - 1)
#define STRLEN(x) ((unsigned) sizeof(""x"") - 1)
/*
* container_of - cast a member of a structure out to the containing structure
@@ -341,10 +341,10 @@ static inline int __coverity_check_and_return__(int condition) {
* negative '-' prefix (hence works correctly on signed
* types). Includes space for the trailing NUL. */
#define DECIMAL_STR_MAX(type) \
(2+(sizeof(type) <= 1 ? 3 : \
sizeof(type) <= 2 ? 5 : \
sizeof(type) <= 4 ? 10 : \
sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
(2U+(sizeof(type) <= 1 ? 3U : \
sizeof(type) <= 2 ? 5U : \
sizeof(type) <= 4 ? 10U : \
sizeof(type) <= 8 ? 20U : (unsigned) sizeof(int[-2*(sizeof(type) > 8)])))
#define DECIMAL_STR_WIDTH(x) \
({ \

View File

@@ -4,6 +4,15 @@
#include "macro.h"
#include "string-util.h"
/* Do some basic checks on STRLEN() and DECIMAL_STR_MAX() */
assert_cc(STRLEN("xxx") == 3);
assert_cc(STRLEN("") == 0);
assert_cc(DECIMAL_STR_MAX(uint8_t) == 5);
assert_cc(DECIMAL_STR_MAX(int8_t) == 5);
assert_cc(DECIMAL_STR_MAX(uint64_t) == 22);
assert_cc(DECIMAL_STR_MAX(char) == 5);
assert_cc(CONST_MAX(DECIMAL_STR_MAX(int8_t), STRLEN("xxx")) == 5);
static void test_format_bytes_one(uint64_t val, bool trailing_B, const char *iec_with_p, const char *iec_without_p,
const char *si_with_p, const char *si_without_p) {
char buf[FORMAT_BYTES_MAX];