sparse/dissect: handle SYM_ENUM
cover sparse/dissect: handle SYM_ENUM
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(-)
PATCH 1/4 sparse/dissect: examine SYM_ENUM nodes
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
--- dissect.c | 9 +++------ test-dissect.c | 17 +++++++++++------ 2 files changed, 14 insertions(+), 12 deletions(-)
dissect.c +3 -6
@@ -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 *parenstatic 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 ;
test-dissect.c +11 -6
@@ -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); }
Signature · 1 line
2.52.0
PATCH 2/4 sparse/dissect: report the usage of enumerators
In reply to Oleg NesterovTest-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
--- dissect.c | 6 +++++- expression.c | 3 +++ expression.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-)
dissect.c +5 -1
@@ -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;
expression.c +3 -0
@@ -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 ; }
expression.h +1 -0
@@ -167,6 +167,7 @@ struct expression {// EXPR_VALUE struct {unsigned long long value; +struct symbol *enum_node;unsigned taint; };
Signature · 1 line
2.52.0
PATCH 3/4 sparse/dissect: shift symscope() callsites into print_usage()
In reply to Oleg NesterovSimplification and preparation for the next change.
--- test-dissect.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-)
test-dissect.c +22 -21
@@ -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, ststruct 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));
Signature · 1 line
2.52.0
PATCH 4/4 sparse/dissect: sanitize the de-anonymization of SYM_ENUMs
In reply to Oleg Nesterovexamine_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>
--- dissect.c | 5 +++-- test-dissect.c | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-)
dissect.c +3 -2
@@ -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);
test-dissect.c +7 -6
@@ -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' )
Signature · 1 line
2.52.0