2 * smatch/check_macro_side_effects.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
12 #include "smatch_slist.h"
13 #include "smatch_expression_stacks.h"
17 static struct string_list
*ignored_macros
;
18 static struct position old_pos
;
20 static struct smatch_state
*alloc_my_state(struct expression
*expr
)
22 struct smatch_state
*state
;
25 state
= __alloc_smatch_state(0);
26 expr
= strip_expr(expr
);
27 name
= get_variable_from_expr_complex(expr
, NULL
);
28 state
->name
= alloc_sname(name
);
34 static int defined_inside_macro(struct position macro_pos
, struct expression
*expr
)
40 name
= get_variable_from_expr(expr
, &sym
);
43 if (!sym
->scope
|| !sym
->scope
->token
)
45 if (positions_eq(macro_pos
, sym
->scope
->token
->pos
))
52 static int affected_inside_macro_before(struct expression
*expr
)
56 struct expression
*old_mod
;
58 sm
= get_sm_state_expr(my_id
, expr
);
62 FOR_EACH_PTR(sm
->possible
, tmp
) {
63 old_mod
= tmp
->state
->data
;
66 if (positions_eq(old_mod
->pos
, expr
->pos
))
68 } END_FOR_EACH_PTR(tmp
);
72 static int is_ignored_macro(const char *macro
)
76 FOR_EACH_PTR(ignored_macros
, tmp
) {
77 if (!strcmp(tmp
, macro
))
79 } END_FOR_EACH_PTR(tmp
);
83 static void match_unop(struct expression
*raw_expr
)
85 struct expression
*expr
;
88 if (raw_expr
->op
!= SPECIAL_INCREMENT
&& raw_expr
->op
!= SPECIAL_DECREMENT
)
91 macro
= get_macro_name(raw_expr
->pos
);
95 expr
= strip_expr(raw_expr
->unop
);
97 if (defined_inside_macro(expr
->pos
, expr
))
100 if (is_ignored_macro(macro
))
103 if (!affected_inside_macro_before(expr
)) {
104 set_state_expr(my_id
, expr
, alloc_my_state(expr
));
109 if (!positions_eq(old_pos
, expr
->pos
))
112 name
= get_variable_from_expr_complex(raw_expr
, NULL
);
113 sm_msg("warn: side effect in macro '%s' doing '%s'",
118 static void match_stmt(struct statement
*stmt
)
120 if (!positions_eq(old_pos
, stmt
->pos
))
124 static void register_ignored_macros(void)
130 snprintf(name
, 256, "%s.ignore_side_effects", option_project_str
);
132 token
= get_tokens_file(name
);
135 if (token_type(token
) != TOKEN_STREAMBEGIN
)
138 while (token_type(token
) != TOKEN_STREAMEND
) {
139 if (token_type(token
) != TOKEN_IDENT
)
141 macro
= alloc_string(show_ident(token
->ident
));
142 add_ptr_list(&ignored_macros
, macro
);
148 void check_macro_side_effects(int id
)
155 add_hook(&match_unop
, OP_HOOK
);
156 add_hook(&match_stmt
, STMT_HOOK
);
157 register_ignored_macros();