Repository: bitcoin/bitcoin (language: cpp)

Issue:
tracepoints: gnu-zero-variadic-macro-arguments warnings
These occur for all tracepoints when using Clang 15 and a system installed `systemtap`:
```bash
# clang --version
Debian clang version 15.0.7

./autogen.sh
./configure CC=clang-15 CXX=clang++-15
make
...
net_processing.cpp:4892:5: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
    TRACE6(net, inbound_message,
    ^
./util/trace.h:18:50: note: expanded from macro 'TRACE6'
#define TRACE6(context, event, a, b, c, d, e, f) DTRACE_PROBE6(context, event, a, b, c, d, e, f)
                                                 ^
/usr/include/aarch64-linux-gnu/sys/sdt.h:494:3: note: expanded from macro 'DTRACE_PROBE6'
  STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6)
  ^
/usr/include/aarch64-linux-gnu/sys/sdt.h:380:3: note: expanded from macro 'STAP_PROBE6'
  _SDT_PROBE(provider, name, 6, (arg1, arg2, arg3, arg4, arg5, arg6))
  ^
/usr/include/aarch64-linux-gnu/sys/sdt.h:78:75: note: expanded from macro '_SDT_PROBE'
    __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \
                                                                          ^
/usr/include/aarch64-linux-gnu/sys/sdt.h:283:9: note: macro '_SDT_ASM_BODY' defined here
#define _SDT_ASM_BODY(provider, name, pack_args, args, ...)                   \
        ^
1 warning generated.
```


Discussion / hints:
FWIW, on Ubuntu Lunar with `systemtap-sdt-dev-4.8` being installed, warnings are gone when configuring with `--enable-c++20`.
> FWIW, on Ubuntu Lunar with `systemtap-sdt-dev-4.8` being installed, warnings are gone when configuring with `--enable-c++20`.

fwiw I don't think systemtap 4.8 is the reason there are no warnings for you. The changes form 4.7 to 4.8 in `includes/sys/sdt.h` file are [minimal](https://sourceware.org/git/?p=systemtap.git;a=commitdiff;h=97213111b28685bf5f3edad5ec9e8bca397e8a5f;hp=6f6f15a002da7a05e64ef24047399688809895b2) and shouldn't affect this.

> > FWIW, on Ubuntu Lunar with `systemtap-sdt-dev-4.8` being installed, warnings are gone when configuring with `--enable-c++20`.
> 
> fwiw I don't think systemtap 4.8 is the reason there are no warnings for you. The changes form 4.7 to 4.8 in `includes/sys/sdt.h` file are [minimal](https://sourceware.org/git/?p=systemtap.git;a=commitdiff;h=97213111b28685bf5f3edad5ec9e8bca397e8a5f;hp=6f6f15a002da7a05e64ef24047399688809895b2) and shouldn't affect this.

Correct, the reason is `--enable-c++20`. See https://en.cppreference.com/w/cpp/preprocessor/replace.
Updated op to note that this is now system-installed systemtap only.
This is still present with https://github.com/bitcoin/bitcoin/pull/26593 as it also uses an underlying variadic macro with 0 arguments via `_SDT_ASM_BODY` -> `_SDT_PROBE` -> `_SDT_PROBE_N` -> `STAP_PROBEV` -> `TRACEPOINT`.

I tried to directly call the `STAP_PROBE1` macro for the single argument case (on top of #26593), which would mean that all our remaining `TRACEPOINT` macros were invoked with >= 1 argument:

```cpp
// A USDT tracepoint with one argument.
#define TRACEPOINT1(context, event) \
    if (TRACEPOINT_ACTIVE(context, event)) \
        STAP_PROBE1(context, event, arg)
```
...but this apparently does not stop the warning, even though we are now never using an empty variadic argument:

```log
wallet/spend.cpp:954:5: warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments]
    TRACEPOINT(coin_selection, selected_coins, wallet.GetName().c_str(), GetAlgorithmName(result.GetAlgo()).c_str(), result.GetTarget(), result.GetWaste(), result.GetSelectedValue());
    ^
./util/trace.h:48:9: note: expanded from macro 'TRACEPOINT'
        STAP_PROBEV(context, event, __VA_ARGS__)
        ^
/usr/include/x86_64-linux-gnu/sys/sdt.h:422:3: note: expanded from macro 'STAP_PROBEV'
  _SDT_PROBE_N(provider, name, _SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__)
  ^
/usr/include/x86_64-linux-gnu/sys/sdt.h:420:3: note: expanded from macro '_SDT_PROBE_N'
  _SDT_PROBE(provider, name, N, (__VA_ARGS__))
  ^
/usr/include/x86_64-linux-gnu/sys/sdt.h:78:75: note: expanded from macro '_SDT_PROBE'
    __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \
                                                                          ^
/usr/include/x86_64-linux-gnu/sys/sdt.h:289:9: note: macro '_SDT_ASM_BODY' defined here
#define _SDT_ASM_BODY(provider, name, pack_args, args, ...)                   \
        ^
```

It seems we have a few options therefore:

1. Do nothing and wait until we move to c++20 (no timeline)
2. Exclude the warning with global compile flags: `CXXFLAGS += -Wno-gnu-zero-variadic-macro-arguments`
3. Add pragmas inside the macros to disable the warnings (diff based on #26593):

```diff
diff --git a/src/util/trace.h b/src/util/trace.h
index 816d8c295..e3fc0d8f4 100644
--- a/src/util/trace.h
+++ b/src/util/trace.h
@@ -32,15 +32,29 @@
 #define TRACEPOINT_ACTIVE(context, event) context##_##event##_semaphore > 0
 
 // A USDT tracepoint with no arguments.
+// Remove pragmas when we switch to c++20
 #define TRACEPOINT0(context, event) \
-    if (TRACEPOINT_ACTIVE(context, event)) \
-        STAP_PROBE(context, event)
+    do { \
+        _Pragma("clang diagnostic push") \
+        _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"") \
+        if (TRACEPOINT_ACTIVE(context, event)) { \
+            STAP_PROBE(context, event); \
+        } \
+        _Pragma("clang diagnostic pop") \
+    } while(0)
 
 // A USDT tracepoint with one to twelve arguments. It's checked that the
 // tracepoint is active before preparing its arguments.
+// Remove pragmas when we switch to c++20
 #define TRACEPOINT(context, event, ...) \
-    if (TRACEPOINT_ACTIVE(context, event)) \
-        STAP_PROBEV(context, event, __VA_ARGS__)
+    do { \
+        _Pragma("clang diagnostic push") \
+        _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"") \
+        if (TRACEPOINT_ACTIVE(context, event)) { \
+            STAP_PROBEV(context, event, __VA_ARGS__); \
+        } \
+        _Pragma("clang diagnostic pop") \
+    } while(0)
 
 #else
 ```

Fix patch:
diff --git a/src/util/trace.h b/src/util/trace.h
index 7a63f39c83f94..051921a0d215b 100644
--- a/src/util/trace.h
+++ b/src/util/trace.h
@@ -9,19 +9,28 @@
 
 #include <sys/sdt.h>
 
-#define TRACE(context, event) DTRACE_PROBE(context, event)
-#define TRACE1(context, event, a) DTRACE_PROBE1(context, event, a)
-#define TRACE2(context, event, a, b) DTRACE_PROBE2(context, event, a, b)
-#define TRACE3(context, event, a, b, c) DTRACE_PROBE3(context, event, a, b, c)
-#define TRACE4(context, event, a, b, c, d) DTRACE_PROBE4(context, event, a, b, c, d)
-#define TRACE5(context, event, a, b, c, d, e) DTRACE_PROBE5(context, event, a, b, c, d, e)
-#define TRACE6(context, event, a, b, c, d, e, f) DTRACE_PROBE6(context, event, a, b, c, d, e, f)
-#define TRACE7(context, event, a, b, c, d, e, f, g) DTRACE_PROBE7(context, event, a, b, c, d, e, f, g)
-#define TRACE8(context, event, a, b, c, d, e, f, g, h) DTRACE_PROBE8(context, event, a, b, c, d, e, f, g, h)
-#define TRACE9(context, event, a, b, c, d, e, f, g, h, i) DTRACE_PROBE9(context, event, a, b, c, d, e, f, g, h, i)
-#define TRACE10(context, event, a, b, c, d, e, f, g, h, i, j) DTRACE_PROBE10(context, event, a, b, c, d, e, f, g, h, i, j)
-#define TRACE11(context, event, a, b, c, d, e, f, g, h, i, j, k) DTRACE_PROBE11(context, event, a, b, c, d, e, f, g, h, i, j, k)
-#define TRACE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l) DTRACE_PROBE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l)
+// Disabling this warning can be removed once we switch to C++20
+#if defined(__clang__) && __cplusplus < 202002L
+#define BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"")
+#define BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP _Pragma("clang diagnostic pop")
+#else
+#define BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH
+#define BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#endif
+
+#define TRACE(context, event) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE(context, event) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE1(context, event, a) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE1(context, event, a) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE2(context, event, a, b) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE2(context, event, a, b) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE3(context, event, a, b, c) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE3(context, event, a, b, c) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE4(context, event, a, b, c, d) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE4(context, event, a, b, c, d) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE5(context, event, a, b, c, d, e) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE5(context, event, a, b, c, d, e) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE6(context, event, a, b, c, d, e, f) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE6(context, event, a, b, c, d, e, f) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE7(context, event, a, b, c, d, e, f, g) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE7(context, event, a, b, c, d, e, f, g) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE8(context, event, a, b, c, d, e, f, g, h) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE8(context, event, a, b, c, d, e, f, g, h) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE9(context, event, a, b, c, d, e, f, g, h, i) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE9(context, event, a, b, c, d, e, f, g, h, i) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE10(context, event, a, b, c, d, e, f, g, h, i, j) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE10(context, event, a, b, c, d, e, f, g, h, i, j) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE11(context, event, a, b, c, d, e, f, g, h, i, j, k) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE11(context, event, a, b, c, d, e, f, g, h, i, j, k) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
+#define TRACE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_PUSH DTRACE_PROBE12(context, event, a, b, c, d, e, f, g, h, i, j, k, l) BITCOIN_DISABLE_WARN_ZERO_VARIADIC_POP
 
 #else
 


Test patch: