Re: [PATCH bpf-next] libbpf: make LIBBPF_OPTS macro strictly a variable declaration
From: Toke Høiland-Jørgensen <hidden>
Date: 2019-10-21 17:18:09
Also in:
bpf
Andrii Nakryiko [off-list ref] writes:
quoted hunk ↗ jump to hunk
LIBBPF_OPTS is implemented as a mix of field declaration and memset + assignment. This makes it neither variable declaration nor purely statements, which is a problem, because you can't mix it with either other variable declarations nor other function statements, because C90 compiler mode emits warning on mixing all that together. This patch changes LIBBPF_OPTS into a strictly declaration of variable and solves this problem, as can be seen in case of bpftool, which previously would emit compiler warning, if done this way (LIBBPF_OPTS as part of function variables declaration block). Signed-off-by: Andrii Nakryiko <redacted> --- tools/bpf/bpftool/prog.c | 6 +++--- tools/lib/bpf/libbpf.h | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-)diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index 27da96a797ab..1a7e8ddf8232 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c@@ -1093,6 +1093,9 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) { struct bpf_object_load_attr load_attr = { 0 }; enum bpf_prog_type common_prog_type = BPF_PROG_TYPE_UNSPEC; + LIBBPF_OPTS(bpf_object_open_opts, open_opts, + .relaxed_maps = relaxed_maps, + ); enum bpf_attach_type expected_attach_type; struct map_replace *map_replace = NULL; struct bpf_program *prog = NULL, *pos;@@ -1106,9 +1109,6 @@ static int load_with_options(int argc, char **argv, bool first_prog_only) const char *file; int idx, err; - LIBBPF_OPTS(bpf_object_open_opts, open_opts, - .relaxed_maps = relaxed_maps, - ); if (!REQ_ARGS(2)) return -1;diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 0fdf086beba7..bf105e9e866f 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h@@ -77,12 +77,13 @@ struct bpf_object_open_attr { * bytes, but that's the best way I've found and it seems to work in practice. */ #define LIBBPF_OPTS(TYPE, NAME, ...) \ - struct TYPE NAME; \ - memset(&NAME, 0, sizeof(struct TYPE)); \ - NAME = (struct TYPE) { \ - .sz = sizeof(struct TYPE), \ - __VA_ARGS__ \ - } + struct TYPE NAME = ({ \ + memset(&NAME, 0, sizeof(struct TYPE)); \ + (struct TYPE) { \ + .sz = sizeof(struct TYPE), \
Wait, you can stick arbitrary code inside a variable initialisation block like this? How does that work? Is everything before the (struct type) just ignored (and is that a cast)? -Toke