Linux SPARSE checker discussions
 help / color / mirror / Atom feed
* [PATCH 0/4] sparse/dissect: fix missing usage reports for unnamed members of named types
@ 2026-06-05 14:56 Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 1/4] sparse/dissect: introduce find_report_member() Oleg Nesterov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-06-05 14:56 UTC (permalink / raw)
  To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse

Hello,

With the recent change, dissect.c correctly reports the definitions of the
promoted members, but it still doesn't report the usages of the underlying
members.

The only functional change is 4/4.

Oleg.
---

 dissect.c | 70 +++++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 50 insertions(+), 20 deletions(-)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] sparse/dissect: introduce find_report_member()
  2026-06-05 14:56 [PATCH 0/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
@ 2026-06-05 14:56 ` Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 2/4] sparse/dissect: fold lookup_member() into find_report_member() Oleg Nesterov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-06-05 14:56 UTC (permalink / raw)
  To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse

No functional changes, preparation for the next patches.

Add the new helper, find_report_member(), which simply does
lookup_member() + report_member(), and update the current users of
the same pattern to use it.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 dissect.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/dissect.c b/dissect.c
index 04ec89ca..6b5cb0ef 100644
--- a/dissect.c
+++ b/dissect.c
@@ -331,6 +331,13 @@ static struct symbol *lookup_member(struct symbol *type, struct ident *name, int
 	return mem;
 }
 
+static struct symbol *find_report_member(usage_t mode, struct position *pos,
+					 struct symbol *type, struct ident *name,
+					 int *p_addr)
+{
+	return report_member(mode, pos, type, lookup_member(type, name, p_addr));
+}
+
 static struct expression *peek_preop(struct expression *expr, int op)
 {
 	do {
@@ -474,8 +481,8 @@ again:
 			p_mode = U_R_VAL;
 		p_type = do_expression(p_mode, expr->deref);
 
-		ret = report_member(mode, &expr->m_pos, p_type,
-			lookup_member(p_type, expr->member, NULL));
+		ret = find_report_member(mode, &expr->m_pos,
+					 p_type, expr->member, NULL);
 	}
 
 	break; case EXPR_OFFSETOF: {
@@ -483,8 +490,8 @@ again:
 
 		do {
 			if (expr->op == '.') {
-				in = report_member(U_VOID, &expr->pos, in,
-					lookup_member(in, expr->ident, NULL));
+				in = find_report_member(U_VOID, &expr->pos,
+							in, expr->ident, NULL);
 			} else {
 				do_expression(U_R_VAL, expr->index);
 				in = in->ctype.base_type;
@@ -609,8 +616,8 @@ static struct symbol *do_initializer(struct symbol *type, struct expression *exp
 
 				m_type = type;
 				while (m_expr->type == EXPR_IDENTIFIER) {
-					m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
-							lookup_member(m_type, m_expr->expr_ident, m_atop));
+					m_type = find_report_member(U_W_VAL, &m_expr->pos,
+								    m_type, m_expr->expr_ident, m_atop);
 					m_expr = m_expr->ident_expression;
 					m_atop = NULL;
 
@@ -621,8 +628,8 @@ static struct symbol *do_initializer(struct symbol *type, struct expression *exp
 				}
 
 				if (m_atop) {
-					m_type = report_member(U_W_VAL, &m_expr->pos, m_type,
-							lookup_member(m_type, NULL, m_atop));
+					m_type = find_report_member(U_W_VAL, &m_expr->pos,
+								    m_type, NULL, m_atop);
 				}
 
 				if (m_expr->type != EXPR_INITIALIZER)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] sparse/dissect: fold lookup_member() into find_report_member()
  2026-06-05 14:56 [PATCH 0/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 1/4] sparse/dissect: introduce find_report_member() Oleg Nesterov
@ 2026-06-05 14:56 ` Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 3/4] sparse/dissect: introduce struct lookup_args for lookup_member() Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 4/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
  3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-06-05 14:56 UTC (permalink / raw)
  To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse

After the previous change lookup_member() has a single caller. Fold it
into find_report_member() and rename __lookup_member().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 dissect.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/dissect.c b/dissect.c
index 6b5cb0ef..c790807e 100644
--- a/dissect.c
+++ b/dissect.c
@@ -283,7 +283,7 @@ static struct symbol *base_type(struct symbol *sym)
 		?: &bad_ctype;
 }
 
-static struct symbol *__lookup_member(struct symbol *type, struct ident *name, int *p_addr)
+static struct symbol *lookup_member(struct symbol *type, struct ident *name, int *p_addr)
 {
 	struct symbol *node;
 	int addr = 0;
@@ -294,7 +294,7 @@ static struct symbol *__lookup_member(struct symbol *type, struct ident *name, i
 				return node;
 		}
 		else if (node->ident == NULL) {
-			node = __lookup_member(node->ctype.base_type, name, NULL);
+			node = lookup_member(node->ctype.base_type, name, NULL);
 			if (node)
 				goto found;
 		}
@@ -310,9 +310,11 @@ found:
 	return NULL;
 }
 
-static struct symbol *lookup_member(struct symbol *type, struct ident *name, int *addr)
+static struct symbol *find_report_member(usage_t mode, struct position *pos,
+					 struct symbol *type, struct ident *name,
+					 int *p_addr)
 {
-	struct symbol *mem = __lookup_member(type, name, addr);
+	struct symbol *mem = lookup_member(type, name, p_addr);
 
 	if (!mem) {
 		static struct symbol bad_member = {
@@ -328,14 +330,7 @@ static struct symbol *lookup_member(struct symbol *type, struct ident *name, int
 		mem->ident = name;
 	}
 
-	return mem;
-}
-
-static struct symbol *find_report_member(usage_t mode, struct position *pos,
-					 struct symbol *type, struct ident *name,
-					 int *p_addr)
-{
-	return report_member(mode, pos, type, lookup_member(type, name, p_addr));
+	return report_member(mode, pos, type, mem);
 }
 
 static struct expression *peek_preop(struct expression *expr, int op)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] sparse/dissect: introduce struct lookup_args for lookup_member()
  2026-06-05 14:56 [PATCH 0/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 1/4] sparse/dissect: introduce find_report_member() Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 2/4] sparse/dissect: fold lookup_member() into find_report_member() Oleg Nesterov
@ 2026-06-05 14:56 ` Oleg Nesterov
  2026-06-05 14:56 ` [PATCH 4/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
  3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-06-05 14:56 UTC (permalink / raw)
  To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse

No functional changes, preparation for the next patch.

The new "struct lookup_args" bundles the current name/p_addr arguments
of lookup_member().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 dissect.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/dissect.c b/dissect.c
index c790807e..3da9e3a2 100644
--- a/dissect.c
+++ b/dissect.c
@@ -283,25 +283,29 @@ static struct symbol *base_type(struct symbol *sym)
 		?: &bad_ctype;
 }
 
-static struct symbol *lookup_member(struct symbol *type, struct ident *name, int *p_addr)
+struct lookup_args {
+	struct ident *name;
+	int *p_addr;
+};
+
+static struct symbol *lookup_member(struct symbol *type, struct lookup_args *la)
 {
 	struct symbol *node;
 	int addr = 0;
 
 	FOR_EACH_PTR(type->symbol_list, node)
-		if (!name) {
-			if (addr == *p_addr)
+		if (!la->name) {
+			if (*la->p_addr == addr)
 				return node;
 		}
 		else if (node->ident == NULL) {
-			node = lookup_member(node->ctype.base_type, name, NULL);
+			node = lookup_member(node->ctype.base_type, la);
 			if (node)
 				goto found;
 		}
-		else if (node->ident == name) {
-found:
-			if (p_addr)
-				*p_addr = addr;
+		else if (node->ident == la->name) {
+found:			if (la->p_addr)
+				*la->p_addr = addr;
 			return node;
 		}
 		addr++;
@@ -314,7 +318,11 @@ static struct symbol *find_report_member(usage_t mode, struct position *pos,
 					 struct symbol *type, struct ident *name,
 					 int *p_addr)
 {
-	struct symbol *mem = lookup_member(type, name, p_addr);
+	struct lookup_args la = {
+		.name	= name,
+		.p_addr	= p_addr,
+	};
+	struct symbol *mem = lookup_member(type, &la);
 
 	if (!mem) {
 		static struct symbol bad_member = {
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] sparse/dissect: fix missing usage reports for unnamed members of named types
  2026-06-05 14:56 [PATCH 0/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
                   ` (2 preceding siblings ...)
  2026-06-05 14:56 ` [PATCH 3/4] sparse/dissect: introduce struct lookup_args for lookup_member() Oleg Nesterov
@ 2026-06-05 14:56 ` Oleg Nesterov
  3 siblings, 0 replies; 5+ messages in thread
From: Oleg Nesterov @ 2026-06-05 14:56 UTC (permalink / raw)
  To: Chris Li, Luc Van Oostenryck; +Cc: Alexey Gladkov, linux-sparse

With the recent change, dissect.c correctly reports the definitions of the
promoted members, but it still doesn't report the usages of the underlying
members.

This means, for example, that

	$ semind search -m r ns_tree.ns_id

finds nothing without this change.

Minimal (same) test-case:

	union U { int i; };

	struct S { union U; } v = { .i = 0 };

Before the patch:

	$ test-dissect TEST.c
	3:8                    def   s S
	1:7                    def   s U
	1:15                   def   m U.i                              int
	3:19                   def   m S.i                              int
	3:23                   def   v v                                struct S
	3:23                   -w-   v v                                struct S
	3:30  v                -w-   m S.i                              int

The usage of U.i is not reported.

After the patch:

	$ test-dissect TEST.c
	3:8                    def   s S
	1:7                    def   s U
	1:15                   def   m U.i                              int
	3:19                   def   m S.i                              int
	3:23                   def   v v                                struct S
	3:23                   -w-   v v                                struct S
	3:30  v                -w-   m U.i                              int
	3:30  v                -w-   m S.i                              int

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 dissect.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/dissect.c b/dissect.c
index 3da9e3a2..2358297b 100644
--- a/dissect.c
+++ b/dissect.c
@@ -286,8 +286,19 @@ static struct symbol *base_type(struct symbol *sym)
 struct lookup_args {
 	struct ident *name;
 	int *p_addr;
+	struct position pos;
+	struct symbol *stack[8];
+	unsigned int depth;
 };
 
+static inline void lookup_push(struct lookup_args *la, struct symbol *type)
+{
+	if (la->depth == ARRAY_SIZE(la->stack))
+		warning(la->pos, "lookup stack overflow");
+	else
+		la->stack[la->depth++] = type;
+}
+
 static struct symbol *lookup_member(struct symbol *type, struct lookup_args *la)
 {
 	struct symbol *node;
@@ -299,9 +310,13 @@ static struct symbol *lookup_member(struct symbol *type, struct lookup_args *la)
 				return node;
 		}
 		else if (node->ident == NULL) {
-			node = lookup_member(node->ctype.base_type, la);
-			if (node)
+			struct symbol *base = node->ctype.base_type;
+			node = lookup_member(base, la);
+			if (node) {
+				if (type->ident != base->ident)
+					lookup_push(la, base);
 				goto found;
+			}
 		}
 		else if (node->ident == la->name) {
 found:			if (la->p_addr)
@@ -321,6 +336,8 @@ static struct symbol *find_report_member(usage_t mode, struct position *pos,
 	struct lookup_args la = {
 		.name	= name,
 		.p_addr	= p_addr,
+		.pos	= *pos,
+		.depth	= 0,
 	};
 	struct symbol *mem = lookup_member(type, &la);
 
@@ -338,6 +355,9 @@ static struct symbol *find_report_member(usage_t mode, struct position *pos,
 		mem->ident = name;
 	}
 
+	while (la.depth)
+		report_member(mode, pos, la.stack[--la.depth], mem);
+
 	return report_member(mode, pos, type, mem);
 }
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-06-05 14:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05 14:56 [PATCH 0/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov
2026-06-05 14:56 ` [PATCH 1/4] sparse/dissect: introduce find_report_member() Oleg Nesterov
2026-06-05 14:56 ` [PATCH 2/4] sparse/dissect: fold lookup_member() into find_report_member() Oleg Nesterov
2026-06-05 14:56 ` [PATCH 3/4] sparse/dissect: introduce struct lookup_args for lookup_member() Oleg Nesterov
2026-06-05 14:56 ` [PATCH 4/4] sparse/dissect: fix missing usage reports for unnamed members of named types Oleg Nesterov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox