* [PATCH 0/4] sparse/dissect: handle SYM_ENUM
@ 2026-01-04 15:21 Oleg Nesterov
2026-01-04 15:21 ` [PATCH 1/4] sparse/dissect: examine SYM_ENUM nodes Oleg Nesterov
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-01-04 15:21 UTC (permalink / raw)
To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse
Chris, Luc, will you ever take or at least review the spam I send? ;)
semind.c:r_member() was not updated yet, this needs to be discussed
with Alexey first.
Oleg.
---
dissect.c | 20 ++++++++++---------
expression.c | 3 +++
expression.h | 1 +
test-dissect.c | 61 ++++++++++++++++++++++++++++++++--------------------------
4 files changed, 49 insertions(+), 36 deletions(-)
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] sparse/dissect: examine SYM_ENUM nodes
2026-01-04 15:21 [PATCH 0/4] sparse/dissect: handle SYM_ENUM Oleg Nesterov
@ 2026-01-04 15:21 ` Oleg Nesterov
2026-01-04 15:22 ` [PATCH 2/4] sparse/dissect: report the usage of enumerators Oleg Nesterov
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-01-04 15:21 UTC (permalink / raw)
To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse
Test-case:
$ cat ENUM_1.c
enum X { A,B } x;
$ ./test-dissect ENUM_1.c
1:16 def v x unsigned int enum X
With this patch:
$ ./test-dissect ENUM_1.c
1:6 def E X unsigned int
1:10 def e X.A unsigned int enum X
1:12 def e X.B unsigned int enum X
1:16 def v x unsigned int enum X
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
dissect.c | 9 +++------
test-dissect.c | 17 +++++++++++------
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/dissect.c b/dissect.c
index b9d4adc4..abca1805 100644
--- a/dissect.c
+++ b/dissect.c
@@ -168,9 +168,6 @@ static struct symbol *report_symbol(usage_t mode, struct expression *expr)
struct symbol *sym = expr_symbol(expr);
struct symbol *ret = base_type(sym);
- if (0 && ret->type == SYM_ENUM)
- return report_member(mode, &expr->pos, ret, expr->symbol);
-
reporter->r_symbol(fix_mode(ret, mode), &expr->pos, sym);
return ret;
@@ -195,7 +192,7 @@ static bool deanon(struct symbol *base, struct ident *node, struct symbol *paren
static void report_memdef(struct symbol *sym, struct symbol *mem)
{
- mem->kind = 'm';
+ mem->kind = sym && sym->type == SYM_ENUM ? 'e' : 'm';
if (sym && mem->ident)
reporter->r_memdef(sym, mem);
}
@@ -235,12 +232,12 @@ static void examine_sym_node(struct symbol *node, struct symbol *parent)
node = base;
break;
- case SYM_STRUCT: case SYM_UNION: //case SYM_ENUM:
+ case SYM_STRUCT: case SYM_UNION: case SYM_ENUM:
if (base->inspected)
return;
base->inspected = 1;
- base->kind = 's';
+ base->kind = base->type == SYM_ENUM ? 'E' : 's';
if (!base->symbol_list)
return;
diff --git a/test-dissect.c b/test-dissect.c
index 65b205f8..3691218d 100644
--- a/test-dissect.c
+++ b/test-dissect.c
@@ -58,13 +58,16 @@ static void r_symbol(unsigned mode, struct position *pos, struct symbol *sym)
switch (sym->kind) {
case 'd':
+ case 't':
break;
+ case 'E':
+ if (sym->type == SYM_ENUM)
+ break;
+ goto err;
case 's':
if (sym->type == SYM_STRUCT || sym->type == SYM_UNION)
break;
goto err;
- case 't':
- break;
case 'f':
if (sym->type != SYM_BAD && sym->ctype.base_type->type != SYM_FN)
goto err;
@@ -84,6 +87,7 @@ err:
static void r_member(unsigned mode, struct position *pos, struct symbol *sym, struct symbol *mem)
{
struct ident *ni, *si, *mi;
+ int mk;
print_usage(pos, sym, mode);
@@ -91,15 +95,16 @@ static void r_member(unsigned mode, struct position *pos, struct symbol *sym, st
si = sym->ident ?: ni;
/* mem == NULL means entire struct accessed */
mi = mem ? (mem->ident ?: ni) : built_in_ident("*");
+ mk = mem ? mem->kind : 'm';
- printf("%c m %.*s.%-*.*s %s\n",
- symscope(sym), si->len, si->name,
+ printf("%c %c %.*s.%-*.*s %s\n",
+ symscope(sym), mk, si->len, si->name,
32-1 - si->len, mi->len, mi->name,
show_typename(mem ? mem->ctype.base_type : sym));
- if (sym->ident && sym->kind != 's')
+ if (sym->ident && sym->kind != 's' && sym->kind != 'E')
warning(*pos, "r_member bad sym type=%d kind=%d", sym->type, sym->kind);
- if (mem && mem->kind != 'm')
+ if (mem && mem->kind != 'm' && mem->kind != 'e')
warning(*pos, "r_member bad mem->kind = %d", mem->kind);
}
--
2.52.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] sparse/dissect: report the usage of enumerators
2026-01-04 15:21 [PATCH 0/4] sparse/dissect: handle SYM_ENUM Oleg Nesterov
2026-01-04 15:21 ` [PATCH 1/4] sparse/dissect: examine SYM_ENUM nodes Oleg Nesterov
@ 2026-01-04 15:22 ` Oleg Nesterov
2026-01-04 15:22 ` [PATCH 3/4] sparse/dissect: shift symscope() callsites into print_usage() Oleg Nesterov
2026-01-04 15:22 ` [PATCH 4/4] sparse/dissect: sanitize the de-anonymization of SYM_ENUMs Oleg Nesterov
3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-01-04 15:22 UTC (permalink / raw)
To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse
Test-case:
$ cat ENUM_2.c
enum X { A, B };
typeof(A) x = B;
$ ./test-dissect ENUM_2.c
2:11 def v x int
2:11 -w- v x int
With this patch:
$ ./test-dissect ENUM_2.c
1:6 def E X unsigned int
1:10 def e X.A unsigned int enum X
1:13 def e X.B unsigned int enum X
2:8 --- e X.A unsigned int enum X
2:11 def v x int
2:11 -w- v x int
2:15 x -r- e X.B unsigned int enum X
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
dissect.c | 6 +++++-
expression.c | 3 +++
expression.h | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dissect.c b/dissect.c
index abca1805..d36986dd 100644
--- a/dissect.c
+++ b/dissect.c
@@ -345,9 +345,13 @@ again:
warning(expr->pos, "bad expr->type: %d", expr->type);
case EXPR_TYPE: // [struct T]; Why ???
- case EXPR_VALUE:
case EXPR_FVALUE:
+ break; case EXPR_VALUE:
+ if (expr->flags & CEF_ENUM)
+ report_member(mode, &expr->pos,
+ base_type(expr->enum_node), expr->enum_node);
+
break; case EXPR_LABEL:
ret = &label_ctype;
diff --git a/expression.c b/expression.c
index b23107da..573358e3 100644
--- a/expression.c
+++ b/expression.c
@@ -479,6 +479,9 @@ struct token *primary_expression(struct token *token, struct expression **tree)
/* we want the right position reported, thus the copy */
expr->pos = token->pos;
expr->flags = CEF_SET_ENUM;
+ // enum { X = bad } results in EXPR_SYMBOL
+ if (expr->type == EXPR_VALUE)
+ expr->enum_node = sym;
token = next;
break;
}
diff --git a/expression.h b/expression.h
index ce8a29ce..b7abff15 100644
--- a/expression.h
+++ b/expression.h
@@ -167,6 +167,7 @@ struct expression {
// EXPR_VALUE
struct {
unsigned long long value;
+ struct symbol *enum_node;
unsigned taint;
};
--
2.52.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] sparse/dissect: shift symscope() callsites into print_usage()
2026-01-04 15:21 [PATCH 0/4] sparse/dissect: handle SYM_ENUM Oleg Nesterov
2026-01-04 15:21 ` [PATCH 1/4] sparse/dissect: examine SYM_ENUM nodes Oleg Nesterov
2026-01-04 15:22 ` [PATCH 2/4] sparse/dissect: report the usage of enumerators Oleg Nesterov
@ 2026-01-04 15:22 ` Oleg Nesterov
2026-01-04 15:22 ` [PATCH 4/4] sparse/dissect: sanitize the de-anonymization of SYM_ENUMs Oleg Nesterov
3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-01-04 15:22 UTC (permalink / raw)
To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse
Simplification and preparation for the next change.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
test-dissect.c | 43 ++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)
diff --git a/test-dissect.c b/test-dissect.c
index 3691218d..e2b8ec9d 100644
--- a/test-dissect.c
+++ b/test-dissect.c
@@ -16,7 +16,17 @@ static inline const char *show_mode(unsigned mode)
return str;
}
-static void print_usage(struct position *pos, struct symbol *sym, unsigned mode)
+static char symscope(struct symbol *sym)
+{
+ if (sym_is_local(sym)) {
+ if (!dissect_ctx)
+ warning(sym->pos, "no context");
+ return '.';
+ }
+ return ' ';
+}
+
+static void print_usage(struct position *pos, struct symbol *sym, unsigned mode, int kind)
{
static unsigned curr_stream = -1;
static struct ident null;
@@ -30,30 +40,21 @@ static void print_usage(struct position *pos, struct symbol *sym, unsigned mode)
if (dissect_ctx)
ctx = dissect_ctx->ident;
- printf("%4d:%-3d %-16.*s %s ",
- pos->line, pos->pos, ctx->len, ctx->name, show_mode(mode));
-
-}
+ printf("%4d:%-3d %-16.*s %s %c %c ",
+ pos->line, pos->pos, ctx->len, ctx->name,
+ show_mode(mode), symscope(sym), kind);
-static char symscope(struct symbol *sym)
-{
- if (sym_is_local(sym)) {
- if (!dissect_ctx)
- warning(sym->pos, "no context");
- return '.';
- }
- return ' ';
}
static void r_symbol(unsigned mode, struct position *pos, struct symbol *sym)
{
- print_usage(pos, sym, mode);
-
if (!sym->ident)
sym->ident = built_in_ident("__asm__");
- printf("%c %c %-32.*s %s\n",
- symscope(sym), sym->kind, sym->ident->len, sym->ident->name,
+ print_usage(pos, sym, mode, sym->kind);
+
+ printf("%-32.*s %s\n",
+ sym->ident->len, sym->ident->name,
show_typename(sym->ctype.base_type));
switch (sym->kind) {
@@ -89,16 +90,16 @@ static void r_member(unsigned mode, struct position *pos, struct symbol *sym, st
struct ident *ni, *si, *mi;
int mk;
- print_usage(pos, sym, mode);
-
ni = built_in_ident("?");
si = sym->ident ?: ni;
/* mem == NULL means entire struct accessed */
mi = mem ? (mem->ident ?: ni) : built_in_ident("*");
mk = mem ? mem->kind : 'm';
- printf("%c %c %.*s.%-*.*s %s\n",
- symscope(sym), mk, si->len, si->name,
+ print_usage(pos, sym, mode, mk);
+
+ printf("%.*s.%-*.*s %s\n",
+ si->len, si->name,
32-1 - si->len, mi->len, mi->name,
show_typename(mem ? mem->ctype.base_type : sym));
--
2.52.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] sparse/dissect: sanitize the de-anonymization of SYM_ENUMs
2026-01-04 15:21 [PATCH 0/4] sparse/dissect: handle SYM_ENUM Oleg Nesterov
` (2 preceding siblings ...)
2026-01-04 15:22 ` [PATCH 3/4] sparse/dissect: shift symscope() callsites into print_usage() Oleg Nesterov
@ 2026-01-04 15:22 ` Oleg Nesterov
3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-01-04 15:22 UTC (permalink / raw)
To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse
examine_sym_node() tries to de-anonymize enums just like structs,
and sometimes it makes sense:
$ ~/tmp/sparse/test-dissect - <<<'enum { X } x;'
1:6 def E :x unsigned int
1:8 def e :x.X unsigned int enum :x
1:12 def v x unsigned int enum :x
But it doesn't make sense to de-anonymize enum types using the name
of its enum_member.
Test-case:
$ cat -n ENUM_3.c
1 enum { A, B };
2 typeof(B) x = A;
$ ./test-dissect ENUM_3.c
1:6 def E :B unsigned int
1:8 def e :B.A unsigned int enum :B
1:11 def e :B.B unsigned int enum :B
2:8 --- e :B.B unsigned int enum :B
2:11 def v x int
2:11 -w- v x int
2:15 x -r- e :B.A unsigned int enum :B
With this patch:
$ ./test-dissect ENUM_3.c
1:8 def e A unsigned int enum <noident>
1:11 def e B unsigned int enum <noident>
2:8 --- e B unsigned int enum <noident>
2:11 def v x int
2:11 -w- v x int
2:15 x -r- e A unsigned int enum <noident>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
dissect.c | 5 +++--
test-dissect.c | 13 +++++++------
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/dissect.c b/dissect.c
index d36986dd..a0fda09c 100644
--- a/dissect.c
+++ b/dissect.c
@@ -245,10 +245,11 @@ static void examine_sym_node(struct symbol *node, struct symbol *parent)
if (toplevel(base->scope))
dissect_ctx = NULL;
- if (base->ident || deanon(base, name, parent))
+ if (base->ident || (!node->enum_member &&
+ deanon(base, name, parent)))
reporter->r_symdef(base);
- if (base->ident)
+ if (base->ident || base->type == SYM_ENUM)
parent = base;
DO_LIST(base->symbol_list, mem,
examine_sym_node(mem, parent);
diff --git a/test-dissect.c b/test-dissect.c
index e2b8ec9d..0a7ee98c 100644
--- a/test-dissect.c
+++ b/test-dissect.c
@@ -88,19 +88,20 @@ err:
static void r_member(unsigned mode, struct position *pos, struct symbol *sym, struct symbol *mem)
{
struct ident *ni, *si, *mi;
- int mk;
+ int mk, ms = 32;
ni = built_in_ident("?");
- si = sym->ident ?: ni;
/* mem == NULL means entire struct accessed */
- mi = mem ? (mem->ident ?: ni) : built_in_ident("*");
mk = mem ? mem->kind : 'm';
+ mi = mem ? (mem->ident ?: ni) : built_in_ident("*");
+ si = sym->ident ?: (mk == 'e' ? NULL : ni);
print_usage(pos, sym, mode, mk);
- printf("%.*s.%-*.*s %s\n",
- si->len, si->name,
- 32-1 - si->len, mi->len, mi->name,
+ if (si)
+ ms -= printf("%.*s.", si->len, si->name);
+
+ printf("%-*.*s %s\n", ms, mi->len, mi->name,
show_typename(mem ? mem->ctype.base_type : sym));
if (sym->ident && sym->kind != 's' && sym->kind != 'E')
--
2.52.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-01-04 15:22 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-04 15:21 [PATCH 0/4] sparse/dissect: handle SYM_ENUM Oleg Nesterov
2026-01-04 15:21 ` [PATCH 1/4] sparse/dissect: examine SYM_ENUM nodes Oleg Nesterov
2026-01-04 15:22 ` [PATCH 2/4] sparse/dissect: report the usage of enumerators Oleg Nesterov
2026-01-04 15:22 ` [PATCH 3/4] sparse/dissect: shift symscope() callsites into print_usage() Oleg Nesterov
2026-01-04 15:22 ` [PATCH 4/4] sparse/dissect: sanitize the de-anonymization of SYM_ENUMs Oleg Nesterov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).