core/debug: detect number of arguments#20166
Conversation
| #ifdef DEVELHELP | ||
| #include "cpu_conf.h" | ||
| #define DEBUG_PRINT(...) \ | ||
| #define DEBUG_PRINT(X, ...) \ |
There was a problem hiding this comment.
That's not standard compliant, as the C standard requires at least on argument to be present for the ....
There was a problem hiding this comment.
the C23 working draft has it so its probably well supported on other compilers (than GCC an clang) too
If there is a ... in the identifier-list in the macro definition, then the trailing arguments (if any),
including any separating comma preprocessing tokens, are merged to form a single item: the variable
arguments.
There was a problem hiding this comment.
#define THREAD_EXTRA_STACKSIZE_PRINTF 42
#define NULL ((void *)0)
typedef struct thread {
/* bla blah doesn't matter */
unsigned stack_size;
} thread_t;
extern int printf(const char *restrict format, ...);
extern int puts(const char *s);
extern thread_t * thread_get_active(void);
#define DEBUG(X, ...) \
do { \
if (sizeof((const char[]){"empty"#__VA_ARGS__}) == sizeof((const char[]){"empty"}))\
printf(X, ##__VA_ARGS__);\
else {\
if ((thread_get_active() == NULL) || \
(thread_get_active()->stack_size >= \
THREAD_EXTRA_STACKSIZE_PRINTF)) { \
printf(X, ##__VA_ARGS__); \
} \
else { \
puts("Cannot debug, stack too small. Consider using DEBUG_PUTS()."); \
} }\
} while (0)
extern int a, b, c, d;
void foo(void) {
DEBUG("Hallo\n");
DEBUG("a = %d\n", a);
DEBUG("a = %d, b = %d\n", a, b);
DEBUG("a = %d, b = %d, c = %d\n", a, b, c);
}$ clang -c -Os -std=c2x -Weverything -o test.o test.c
test.c:16:21: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
16 | printf(X, ##__VA_ARGS__);\
| ^
test.c:21:29: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
21 | printf(X, ##__VA_ARGS__); \
| ^
test.c:16:23: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
16 | printf(X, ##__VA_ARGS__);\
| ^
test.c:21:31: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
21 | printf(X, ##__VA_ARGS__); \
| ^
test.c:16:23: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
16 | printf(X, ##__VA_ARGS__);\
| ^
test.c:21:31: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
21 | printf(X, ##__VA_ARGS__); \
| ^
test.c:16:23: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
16 | printf(X, ##__VA_ARGS__);\
| ^
test.c:21:31: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
21 | printf(X, ##__VA_ARGS__); \
| ^
test.c:30:6: warning: no previous prototype for function 'foo' [-Wmissing-prototypes]
30 | void foo(void) {
| ^
test.c:30:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
30 | void foo(void) {
| ^
| static
9 warnings generated.There was a problem hiding this comment.
<source>: .. warning: no previous prototype for function 'foo' [-Wmissing-prototypes]
are you sure that is a applicable warning level ?
There was a problem hiding this comment.
#define DEBUG(X, ...) \
do { \
if (sizeof((const char[]){"empty"#__VA_ARGS__}) == sizeof((const char[]){"empty"}))\
printf(X __VA_OPT__(,) __VA_ARGS__);\
else {\
if ((thread_get_active() == NULL) || \
(thread_get_active()->stack_size >= \
THREAD_EXTRA_STACKSIZE_PRINTF)) { \
printf(X __VA_OPT__(,) __VA_ARGS__); \
} \
else { \
puts("Cannot debug, stack too small. Consider using DEBUG_PUTS()."); \
} }\
} while (0)
would be the solution following the c2x draft but clang doesn't like that either :
-Os -std=c2x -Weverything
Output of x86-64 clang 17.0.1 (Compiler #1)
<source>:32:20: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
32 | DEBUG("Hallo\n");
seems like clangs warnings are not up to date
kaspar030
left a comment
There was a problem hiding this comment.
NACK.
- using GCC specifics
- making the macro larger instead of removing it
- really, "detect number of arguments" in the preprocessor? RIOT markets itself as "the friendly operating system", and this definitely isn't.
|
Btw: I don't think we would need the bail out mechanism anymore if we would switch to picolibc. Maybe this is something that we could push instead and get rid of the bail out entirely? |
Contribution description
this adds a number of arguments detection for the DEBUG_PRINT Macro to avoid the not very helpful "I don't print because the thread stack is to small" for cases that are cought by the printf to puts conversion (which is active starting on -O0 on gcc and llvm
Testing procedure
Debug print?
Issues/PRs references