Re: [PATCH] sparse/pre-process: introduce "dissect_mode" option to fix dissect/semind
Chris Li <[email protected]> Fri, 16 Jan 2026 15:29:41 -0800
| Newsgroups | org.kernel.vger.linux-sparse |
|---|---|
| Message-ID | <CACePvbW2OybP7P-Vk+pa23SqA0+R0i8=20TiQMq99PvNAYJ8GA@mail.gmail.com> |
Hi Oleg, Slowly catching up my back log from the holidays. On Wed, Dec 17, 2025 at 7:26 AM Oleg Nesterov <[email protected]> wrote: > > I don't quite understand why does expand() -> collect_arg() path > update ->pos for each token in the input *list, but this breaks > dissect and thus semind. That is a good question, I don't understand why it did that either. I did some digging, inside macro argument list expansion, the "#include " is not allowed. It is not possible to switch streams here. The "pos.pos" is for human consumption anyway, it has no effect on the IR generation. The only visible effect as far as I can tell is related to the preprocessor "-E" in lib.c: if (preprocess_only) { while (!eof_token(token)) { int prec = 1; struct token *next = token->next; const char *separator = ""; if (next->pos.whitespace) separator = " "; if (next->pos.newline) { separator = "\n\t\t\t\t\t"; prec = next->pos.pos; <--- use pos as indentation level. if (prec > 4) prec = 4; } printf("%s%.*s", show_token(token), prec, separator); token = next; The "-E" output has some indentation enhancement to turn space into tab level indentation. This "pos" assignment tries to align the indentation context of the input arguments to the same level of the expanding macro name. > Test-case: > > $ cat -n PP_POS.c > 1 #define READ_ONCE(x) x > 2 #define WRITE_ONCE(x, y) x = y > 3 > 4 int R, W; > 5 > 6 void func(void) > 7 { > 8 WRITE_ONCE( > 9 W, With your patch, when doing "-E", the W will get indentation deeper than WRITE_ONCE. > 10 READ_ONCE(R) > 11 ); > 12 } > > $ ./test-dissect PP_POS.c > 4:5 def v R int > 4:8 def v W int > 6:6 def f func void ( ... ) > 8:3 func -w- v W int > 8:3 func -r- v R int > > The reported positions of the usage of R and W are wrong, > and thus ./semind doesn't work: It seems to me this enhancement can be used on other macro related expansions as well. > > $ ./semind add PP_POS.c > $ ./semind search -l PP_POS.c:10:16 > > With this patch: > > $ ./test-dissect PP_POS.c > 4:5 def v R int > 4:8 def v W int > 6:6 def f func void ( ... ) > 9:6 func -w- v W int > 10:16 func -r- v R int > > $ ./semind add PP_POS.c > $ ./semind search -l PP_POS.c:10:16 > (def) PP_POS.c 4 5 int R, W; > (-r-) PP_POS.c 10 16 func READ_ONCE(R) > > Signed-off-by: Oleg Nesterov <[email protected]> > --- > dissect.c | 1 + > options.c | 1 + > options.h | 1 + > pre-process.c | 8 +++++--- > 4 files changed, 8 insertions(+), 3 deletions(-) > > diff --git a/dissect.c b/dissect.c > index a6003afa..5fed8e22 100644 > --- a/dissect.c > +++ b/dissect.c > @@ -714,6 +714,7 @@ end: > > void dissect(struct reporter *rep, struct string_list *filelist) > { > + dissect_mode = 1; I don't think we need dissect_mode. I am leaning towards enabling it all the time, maybe except for the preprocessor only mode. > reporter = rep; > > DO_LIST(filelist, file, do_file(file)); > diff --git a/options.c b/options.c > index 6ee4d878..0f207e80 100644 > --- a/options.c > +++ b/options.c > @@ -71,6 +71,7 @@ int dump_macro_defs = 0; > int dump_macros_only = 0; > > int dissect_show_all_symbols = 0; > +int dissect_mode = 0; > > unsigned long fdump_ir; > int fhosted = 1; > diff --git a/options.h b/options.h > index c2a9551a..b559254d 100644 > --- a/options.h > +++ b/options.h > @@ -71,6 +71,7 @@ extern int dump_macro_defs; > extern int dump_macros_only; > > extern int dissect_show_all_symbols; > +extern int dissect_mode; > > extern unsigned long fdump_ir; > extern int fhosted; > diff --git a/pre-process.c b/pre-process.c > index 3fb25082..64445881 100644 > --- a/pre-process.c > +++ b/pre-process.c > @@ -294,9 +294,11 @@ static struct token *collect_arg(struct token *prev, int vararg, struct position > } else if (match_op(next, ',') && !nesting && !vararg) { > break; > } > - next->pos.stream = pos->stream; > - next->pos.line = pos->line; > - next->pos.pos = pos->pos; > + if (!dissect_mode) { > + next->pos.stream = pos->stream; > + next->pos.line = pos->line; > + next->pos.pos = pos->pos; > + } Maybe change it to "if (preprocess_only)", and fix all the validation error output of the checker. What do you say? Overall I feel that without this position overwrite is better to locate the real location of the argument of the macro. If anyone knows another reason we should do the position overwrite, please let me know. Alternatively we can also fix the preprocessor "-E" indentation output. Might not be worth the complexity. Chris > next->pos.newline = 0; > p = &next->next; > } > -- > 2.52.0 > >