On Mon, Nov 8, 2021 at 7:38 PM Alexei Starovoitov <alexei.starovoitov@xxxxxxxxx> wrote: > > On Sun, Nov 07, 2021 at 10:13:11PM -0800, Andrii Nakryiko wrote: > > +#define btf_dump__new(a1, a2, a3, a4) __builtin_choose_expr( \ > > + __builtin_types_compatible_p(typeof(a4), btf_dump_printf_fn_t) + \ > > + __builtin_types_compatible_p(typeof(a4), \ > > + void(void *, const char *, va_list)), \ > > + btf_dump__new_deprecated((void *)a1, (void *)a2, (void *)a3, (void *)a4),\ > > + btf_dump__new((void *)a1, (void *)a2, (void *)a3, (void *)a4)) > > why '+' in the above? The return type of __builtin_types_compatible_p() is bool. > What is bool + bool ? > It suppose to be logical 'OR', right? __builtin_types_compatible_p() is defined as returning 0 or 1 (not true/false). And __builtin_choose_expr() is also defined as comparing first argument against 0, not as true/false. But in practice it doesn't matter because bool is converted to 0 or 1 in arithmetic operations. So I can switch to || with no effect. Let me know if you still prefer logical || and I'll change. But yes to your last question, it's logical OR. > > Maybe checking for ops type would be more robust ? opts can be NULL. At which point it's actually only compatible with void *. The only non-null args are btf (same for both variants, so no go) or callback. So I have to check the callback. From my experimentations with various possible invocations (locally, not in any test), this check is quite robust. I need to check two types: pointer to func and func itself (C allows that, turns out; I learned it from [0]). [0] https://github.com/cilium/ebpf/issues/214 > Like: > #define btf_dump__new(a1, a2, a3, a4) __builtin_choose_expr( \ > __builtin_types_compatible_p(typeof(a4), const struct btf_dump_opts*), \ > btf_dump__new((void *)a1, (void *)a2, (void *)a3, (void *)a4), \ > btf_dump__new_deprecated((void *)a1, (void *)a2, (void *)a3, (void *)a4))