linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).