4 * Started by Oleg Nesterov <oleg@tv-sign.ru>
6 * Licensed under the Open Software License version 1.1
12 #define U_SELF ((1 << U_SHIFT) - 1)
13 #define U_MASK (U_R_VAL | U_W_VAL | U_R_AOF)
15 #define DO_LIST(l__, p__, expr__) \
17 typeof(l__->list[0]) p__; \
18 FOR_EACH_PTR(l__, p__) \
20 END_FOR_EACH_PTR(p__); \
23 #define DO_2_LIST(l1__,l2__, p1__,p2__, expr__) \
25 typeof(l1__->list[0]) p1__; \
26 typeof(l2__->list[0]) p2__; \
27 PREPARE_PTR_LIST(l1__, p1__); \
28 FOR_EACH_PTR(l2__, p2__) \
30 NEXT_PTR_LIST(p1__); \
31 END_FOR_EACH_PTR(p2__); \
32 FINISH_PTR_LIST(p1__); \
36 typedef unsigned usage_t
;
38 static struct reporter
*reporter
;
39 static struct symbol
*return_type
;
41 static void do_sym_list(struct symbol_list
*list
);
44 *base_type(struct symbol
*sym
),
45 *do_initializer(struct symbol
*type
, struct expression
*expr
),
46 *do_expression(usage_t mode
, struct expression
*expr
),
47 *do_statement(usage_t mode
, struct statement
*stmt
);
49 static inline int is_ptr(struct symbol
*type
)
51 return type
->type
== SYM_PTR
|| type
->type
== SYM_ARRAY
;
54 static inline usage_t
u_rval(usage_t mode
)
56 return mode
& (U_R_VAL
| (U_MASK
<< U_SHIFT
))
60 static inline usage_t
u_addr(usage_t mode
)
62 return mode
= mode
& U_MASK
63 ? U_R_AOF
| (mode
& U_W_AOF
) : 0;
66 static usage_t
u_lval(struct symbol
*type
)
68 int wptr
= is_ptr(type
) && !(type
->ctype
.modifiers
& MOD_CONST
);
69 return wptr
|| type
== &bad_ctype
70 ? U_W_AOF
| U_R_VAL
: U_R_VAL
;
73 static usage_t
fix_mode(struct symbol
*type
, usage_t mode
)
75 mode
&= (U_SELF
| (U_SELF
<< U_SHIFT
));
79 if (!type
->ctype
.base_type
)
90 mode
&= ~(U_R_VAL
| U_W_AOF
);
92 break; case SYM_ARRAY
:
93 if (mode
& (U_MASK
<< U_SHIFT
))
95 else if (mode
!= U_W_VAL
)
99 if (!(mode
& U_R_AOF
))
105 static inline struct symbol
*no_member(struct ident
*name
)
107 static struct symbol sym
= {
111 sym
.ctype
.base_type
= &bad_ctype
;
117 static struct symbol
*report_member(mode_t mode
, struct position
*pos
,
118 struct symbol
*type
, struct symbol
*mem
)
120 struct symbol
*ret
= mem
->ctype
.base_type
;
122 if (reporter
->r_member
)
123 reporter
->r_member(fix_mode(ret
, mode
), pos
, type
, mem
);
128 static void report_implicit(usage_t mode
, struct position
*pos
, struct symbol
*type
)
130 if (type
->type
!= SYM_STRUCT
&& type
->type
!= SYM_UNION
)
133 if (!reporter
->r_member
)
136 if (type
->ident
!= NULL
)
137 reporter
->r_member(mode
, pos
, type
, NULL
);
139 DO_LIST(type
->symbol_list
, mem
,
140 report_implicit(mode
, pos
, base_type(mem
)));
143 static inline struct symbol
*expr_symbol(struct expression
*expr
)
145 struct symbol
*sym
= expr
->symbol
;
148 sym
= lookup_symbol(expr
->symbol_name
, NS_SYMBOL
);
151 sym
= alloc_symbol(expr
->pos
, SYM_BAD
);
152 bind_symbol(sym
, expr
->symbol_name
, NS_SYMBOL
);
153 sym
->ctype
.modifiers
= MOD_EXTERN
;
157 if (!sym
->ctype
.base_type
)
158 sym
->ctype
.base_type
= &bad_ctype
;
163 static struct symbol
*report_symbol(usage_t mode
, struct expression
*expr
)
165 struct symbol
*sym
= expr_symbol(expr
);
166 struct symbol
*ret
= base_type(sym
);
168 if (0 && ret
->type
== SYM_ENUM
)
169 return report_member(mode
, &expr
->pos
, ret
, expr
->symbol
);
171 if (reporter
->r_symbol
)
172 reporter
->r_symbol(fix_mode(ret
, mode
), &expr
->pos
, sym
);
177 static inline struct ident
*mk_name(struct ident
*root
, struct ident
*node
)
181 snprintf(name
, sizeof(name
), "%.*s:%.*s",
182 root
? root
->len
: 0, root
? root
->name
: "",
183 node
? node
->len
: 0, node
? node
->name
: "");
185 return built_in_ident(name
);
188 static void examine_sym_node(struct symbol
*node
, struct ident
*root
)
199 while ((base
= node
->ctype
.base_type
) != NULL
)
200 switch (base
->type
) {
202 node
->ctype
.base_type
=
203 do_expression(U_VOID
, base
->initializer
);
207 do_expression(U_R_VAL
, base
->array_size
);
208 case SYM_PTR
: case SYM_FN
:
212 case SYM_STRUCT
: case SYM_UNION
: //case SYM_ENUM:
215 if (!base
->symbol_list
)
219 if (!base
->ident
&& name
)
220 base
->ident
= mk_name(root
, name
);
221 if (base
->ident
&& reporter
->r_symdef
)
222 reporter
->r_symdef(base
);
223 DO_LIST(base
->symbol_list
, mem
,
224 examine_sym_node(mem
, base
->ident
?: root
));
230 static struct symbol
*base_type(struct symbol
*sym
)
235 if (sym
->type
== SYM_NODE
)
236 examine_sym_node(sym
, NULL
);
238 return sym
->ctype
.base_type
// builtin_fn_type
242 static struct symbol
*__lookup_member(struct symbol
*type
, struct ident
*name
, int *p_addr
)
247 FOR_EACH_PTR(type
->symbol_list
, node
)
252 else if (node
->ident
== NULL
) {
253 node
= __lookup_member(node
->ctype
.base_type
, name
, NULL
);
257 else if (node
->ident
== name
) {
264 END_FOR_EACH_PTR(node
);
269 static struct symbol
*lookup_member(struct symbol
*type
, struct ident
*name
, int *addr
)
271 return __lookup_member(type
, name
, addr
)
275 static struct expression
*peek_preop(struct expression
*expr
, int op
)
278 if (expr
->type
!= EXPR_PREOP
)
291 static struct symbol
*do_expression(usage_t mode
, struct expression
*expr
)
293 struct symbol
*ret
= &int_ctype
;
296 if (expr
) switch (expr
->type
) {
298 warning(expr
->pos
, "bad expr->type: %d", expr
->type
);
300 case EXPR_TYPE
: // [struct T]; Why ???
304 break; case EXPR_LABEL
:
307 break; case EXPR_STRING
:
310 break; case EXPR_STATEMENT
:
311 ret
= do_statement(mode
, expr
->statement
);
313 break; case EXPR_SIZEOF
: case EXPR_ALIGNOF
: case EXPR_PTRSIZEOF
:
314 do_expression(U_VOID
, expr
->cast_expression
);
316 break; case EXPR_COMMA
:
317 do_expression(U_VOID
, expr
->left
);
318 ret
= do_expression(mode
, expr
->right
);
320 break; case EXPR_CAST
: case EXPR_FORCE_CAST
: //case EXPR_IMPLIED_CAST:
321 ret
= base_type(expr
->cast_type
);
322 do_initializer(ret
, expr
->cast_expression
);
324 break; case EXPR_COMPARE
: case EXPR_LOGICAL
:
326 do_expression(mode
, expr
->left
);
327 do_expression(mode
, expr
->right
);
329 break; case EXPR_CONDITIONAL
: //case EXPR_SELECT:
330 do_expression(expr
->cond_true
331 ? U_R_VAL
: U_R_VAL
| mode
,
333 ret
= do_expression(mode
, expr
->cond_true
);
334 ret
= do_expression(mode
, expr
->cond_false
);
336 break; case EXPR_CALL
:
337 ret
= do_expression(U_R_PTR
, expr
->fn
);
339 ret
= ret
->ctype
.base_type
;
340 DO_2_LIST(ret
->arguments
, expr
->args
, arg
, val
,
341 do_expression(u_lval(base_type(arg
)), val
));
342 ret
= ret
->type
== SYM_FN
? base_type(ret
)
345 break; case EXPR_ASSIGNMENT
:
346 mode
|= U_W_VAL
| U_R_VAL
;
349 ret
= do_expression(mode
, expr
->left
);
350 report_implicit(mode
, &expr
->pos
, ret
);
351 mode
= expr
->op
== '='
352 ? u_lval(ret
) : U_R_VAL
;
353 do_expression(mode
, expr
->right
);
355 break; case EXPR_BINOP
: {
356 struct symbol
*l
, *r
;
357 mode
|= u_rval(mode
);
358 l
= do_expression(mode
, expr
->left
);
359 r
= do_expression(mode
, expr
->right
);
360 if (expr
->op
!= '+' && expr
->op
!= '-')
362 else if (!is_ptr_type(r
))
364 else if (!is_ptr_type(l
))
368 break; case EXPR_PREOP
: case EXPR_POSTOP
: {
369 struct expression
*unop
= expr
->unop
;
372 case SPECIAL_INCREMENT
:
373 case SPECIAL_DECREMENT
:
374 mode
|= U_W_VAL
| U_R_VAL
;
376 mode
|= u_rval(mode
);
378 ret
= do_expression(mode
, unop
);
381 if ((expr
= peek_preop(unop
, '*')))
383 ret
= alloc_symbol(unop
->pos
, SYM_PTR
);
384 ret
->ctype
.base_type
=
385 do_expression(u_addr(mode
), unop
);
388 if ((expr
= peek_preop(unop
, '&')))
390 if (mode
& (U_MASK
<< U_SHIFT
))
393 if (mode
& (U_R_AOF
<< U_SHIFT
))
395 if (mode
& (U_W_VAL
<< U_SHIFT
))
397 ret
= do_expression(mode
, unop
);
398 ret
= is_ptr(ret
) ? base_type(ret
)
403 break; case EXPR_DEREF
: {
404 struct symbol
*p_type
;
407 p_mode
= mode
& U_SELF
;
408 if (!(mode
& U_MASK
) && (mode
& (U_MASK
<< U_SHIFT
)))
410 p_type
= do_expression(p_mode
, expr
->deref
);
412 ret
= report_member(mode
, &expr
->pos
, p_type
,
413 lookup_member(p_type
, expr
->member
, NULL
));
416 break; case EXPR_SYMBOL
:
417 ret
= report_symbol(mode
, expr
);
423 static void do_asm_xputs(usage_t mode
, struct expression_list
*xputs
)
429 do_expression(U_W_AOF
| mode
, expr
));
432 static struct symbol
*do_statement(usage_t mode
, struct statement
*stmt
)
434 struct symbol
*ret
= &void_ctype
;
436 if (stmt
) switch (stmt
->type
) {
438 warning(stmt
->pos
, "bad stmt->type: %d", stmt
->type
);
444 break; case STMT_DECLARATION
:
445 do_sym_list(stmt
->declaration
);
447 break; case STMT_EXPRESSION
:
448 ret
= do_expression(mode
, stmt
->expression
);
450 break; case STMT_RETURN
:
451 do_expression(u_lval(return_type
), stmt
->expression
);
453 break; case STMT_ASM
:
454 do_expression(U_R_VAL
, stmt
->asm_string
);
455 do_asm_xputs(U_W_VAL
, stmt
->asm_outputs
);
456 do_asm_xputs(U_R_VAL
, stmt
->asm_inputs
);
458 break; case STMT_COMPOUND
: {
461 count
= statement_list_size(stmt
->stmts
);
462 DO_LIST(stmt
->stmts
, st
,
463 ret
= do_statement(--count
? U_VOID
: mode
, st
));
466 break; case STMT_ITERATOR
:
467 do_sym_list(stmt
->iterator_syms
);
468 do_statement(U_VOID
, stmt
->iterator_pre_statement
);
469 do_expression(U_R_VAL
, stmt
->iterator_pre_condition
);
470 do_statement(U_VOID
, stmt
->iterator_post_statement
);
471 do_statement(U_VOID
, stmt
->iterator_statement
);
472 do_expression(U_R_VAL
, stmt
->iterator_post_condition
);
475 do_expression(U_R_VAL
, stmt
->if_conditional
);
476 do_statement(U_VOID
, stmt
->if_true
);
477 do_statement(U_VOID
, stmt
->if_false
);
479 break; case STMT_SWITCH
:
480 do_expression(U_R_VAL
, stmt
->switch_expression
);
481 do_statement(U_VOID
, stmt
->switch_statement
);
483 break; case STMT_CASE
:
484 do_expression(U_R_VAL
, stmt
->case_expression
);
485 do_expression(U_R_VAL
, stmt
->case_to
);
486 do_statement(U_VOID
, stmt
->case_statement
);
488 break; case STMT_GOTO
:
489 do_expression(U_R_PTR
, stmt
->goto_expression
);
491 break; case STMT_LABEL
:
492 do_statement(mode
, stmt
->label_statement
);
499 static struct symbol
*do_initializer(struct symbol
*type
, struct expression
*expr
)
501 struct symbol
*m_type
;
502 struct expression
*m_expr
;
505 if (expr
) switch (expr
->type
) {
507 do_expression(u_lval(type
), expr
);
509 break; case EXPR_INDEX
:
510 do_initializer(base_type(type
), expr
->idx_expression
);
512 break; case EXPR_INITIALIZER
:
514 FOR_EACH_PTR(expr
->expr_list
, m_expr
)
515 if (type
->type
== SYM_ARRAY
) {
516 m_type
= base_type(type
);
517 if (m_expr
->type
== EXPR_INDEX
)
518 m_expr
= m_expr
->idx_expression
;
520 struct position
*pos
= &m_expr
->pos
;
521 struct ident
*m_name
= NULL
;
523 if (m_expr
->type
== EXPR_IDENTIFIER
) {
524 m_name
= m_expr
->expr_ident
;
525 m_expr
= m_expr
->ident_expression
;
528 m_type
= report_member(U_W_VAL
, pos
, type
,
529 lookup_member(type
, m_name
, &m_addr
));
530 if (m_expr
->type
!= EXPR_INITIALIZER
)
531 report_implicit(U_W_VAL
, pos
, m_type
);
533 do_initializer(m_type
, m_expr
);
535 END_FOR_EACH_PTR(m_expr
);
541 static inline struct symbol
*do_symbol(struct symbol
*sym
)
545 type
= base_type(sym
);
547 if (reporter
->r_symdef
)
548 reporter
->r_symdef(sym
);
550 switch (type
->type
) {
552 if (!sym
->initializer
)
554 if (reporter
->r_symbol
)
555 reporter
->r_symbol(U_W_VAL
, &sym
->pos
, sym
);
556 do_initializer(type
, sym
->initializer
);
559 do_sym_list(type
->arguments
);
560 return_type
= base_type(type
);
561 do_statement(U_VOID
, sym
->ctype
.modifiers
& MOD_INLINE
569 static void do_sym_list(struct symbol_list
*list
)
571 DO_LIST(list
, sym
, do_symbol(sym
));
574 void dissect(struct symbol_list
*list
, struct reporter
*rep
)