Skip to content

core/debug: detect number of arguments#20166

Open
kfessel wants to merge 2 commits intoRIOT-OS:masterfrom
kfessel:p-debug-n-arg-detect
Open

core/debug: detect number of arguments#20166
kfessel wants to merge 2 commits intoRIOT-OS:masterfrom
kfessel:p-debug-n-arg-detect

Conversation

@kfessel
Copy link
Copy Markdown
Contributor

@kfessel kfessel commented Dec 11, 2023

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

@kfessel kfessel requested a review from kaspar030 as a code owner December 11, 2023 11:01
@github-actions github-actions bot added the Area: core Area: RIOT kernel. Handle PRs marked with this with care! label Dec 11, 2023
@kfessel kfessel requested a review from maribu December 11, 2023 11:04
#ifdef DEVELHELP
#include "cpu_conf.h"
#define DEBUG_PRINT(...) \
#define DEBUG_PRINT(X, ...) \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not standard compliant, as the C standard requires at least on argument to be present for the ....

Copy link
Copy Markdown
Contributor Author

@kfessel kfessel Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the C23 working draft has it so its probably well supported on other compilers (than GCC an clang) too

https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf p178:

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<source>: .. warning: no previous prototype for function 'foo' [-Wmissing-prototypes] 

are you sure that is a applicable warning level ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#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

@kfessel kfessel added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Dec 11, 2023
@riot-ci
Copy link
Copy Markdown

riot-ci commented Dec 11, 2023

Murdock results

✔️ PASSED

6dd4169 core/debug: detect nargs but not for everyone

Success Failures Total Runtime
8082 0 8082 11m:27s

Artifacts

Copy link
Copy Markdown
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@maribu
Copy link
Copy Markdown
Member

maribu commented Dec 11, 2023

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: core Area: RIOT kernel. Handle PRs marked with this with care! CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants