[PATCH 1/4] sparse/dissect: examine SYM_ENUM nodes

Oleg Nesterov <[email protected]> Sun, 4 Jan 2026 16:21:56 +0100
Newsgroups org.kernel.vger.linux-sparse
Message-ID <[email protected]>
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 <[email protected]>
---
 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