From: Dan Carpenter Date: Fri, 15 Mar 2013 19:54:32 +0000 (+0300) Subject: flow: handle POST_OPs correctly X-Git-Tag: 1.59~253 X-Git-Url: https://repo.or.cz/w/smatch.git/commitdiff_plain/c4912d2a16799c4736e682e233120af269af5775 flow: handle POST_OPs correctly Basically we put the POST_OPs onto a stack for processing later when we hit a sequence point. In C there are 5 kinds of sequence points. 1) The end of a statement 2) A comma 3) After we finish processing the arguments to a function call 4) When we hit an || or an && 5) At the end of a condition So at those points then we process the POST_OPs and empty the POST_OP stack. Signed-off-by: Dan Carpenter --- diff --git a/smatch.h b/smatch.h index e1f2ed53..38274ab5 100644 --- a/smatch.h +++ b/smatch.h @@ -324,6 +324,7 @@ void smatch (int argc, char **argv); int inside_loop(void); struct expression *get_switch_expr(void); int in_expression_statement(void); +void __process_post_op_stack(void); void __split_expr(struct expression *expr); void __split_stmt(struct statement *stmt); extern int option_assume_loops; diff --git a/smatch_conditions.c b/smatch_conditions.c index 6684e087..9450d3dd 100644 --- a/smatch_conditions.c +++ b/smatch_conditions.c @@ -162,6 +162,7 @@ static void handle_logical(struct expression *expr) */ split_conditions(expr->left); + __process_post_op_stack(); if (!is_logical_and(expr)) __use_cond_false_states(); @@ -170,6 +171,7 @@ static void handle_logical(struct expression *expr) __save_pre_cond_states(); split_conditions(expr->right); + __process_post_op_stack(); __discard_pre_cond_states(); if (is_logical_and(expr)) @@ -254,6 +256,7 @@ static void handle_select(struct expression *expr) __push_cond_stacks(); __push_fake_cur_slist(); split_conditions(expr->cond_true); + __process_post_op_stack(); a_T_b_fake = __pop_fake_cur_slist(); a_T_b_T = combine(a_T, a_T_b_fake, __pop_cond_true_stack()); a_T_b_F = combine(a_T, a_T_b_fake, __pop_cond_false_stack()); @@ -394,6 +397,7 @@ static void split_conditions(struct expression *expr) } else if (expr->type == EXPR_POSTOP) { __split_expr(expr); } + __process_post_op_stack(); pop_expression(&big_expression_stack); } diff --git a/smatch_flow.c b/smatch_flow.c index 7e86c28b..8d41cc63 100644 --- a/smatch_flow.c +++ b/smatch_flow.c @@ -30,6 +30,7 @@ static char *cur_func; static int loop_count; int __expr_stmt_count; static struct expression_list *switch_expr_stack = NULL; +static struct expression_list *post_op_stack = NULL; struct expression_list *big_expression_stack; struct statement_list *big_statement_stack; @@ -131,6 +132,17 @@ int inlinable(struct expression *expr) return 0; } +void __process_post_op_stack(void) +{ + struct expression *expr; + + FOR_EACH_PTR(post_op_stack, expr) { + __pass_to_client(expr, OP_HOOK); + } END_FOR_EACH_PTR(expr); + + __free_ptr_list((struct ptr_list **)&post_op_stack); +} + void __split_expr(struct expression *expr) { if (!expr) @@ -146,9 +158,12 @@ void __split_expr(struct expression *expr) case EXPR_PREOP: if (expr->op == '*') __pass_to_client(expr, DEREF_HOOK); - case EXPR_POSTOP: + __split_expr(expr->unop); __pass_to_client(expr, OP_HOOK); + break; + case EXPR_POSTOP: __split_expr(expr->unop); + push_expression(&post_op_stack, expr); break; case EXPR_STATEMENT: __expr_stmt_count++; @@ -164,6 +179,7 @@ void __split_expr(struct expression *expr) __pass_to_client(expr, BINOP_HOOK); case EXPR_COMMA: __split_expr(expr->left); + __process_post_op_stack(); __split_expr(expr->right); break; case EXPR_ASSIGNMENT: { @@ -243,6 +259,7 @@ void __split_expr(struct expression *expr) add_inline_function(expr->fn->symbol); if (inlinable(expr->fn)) __inline_call = 1; + __process_post_op_stack(); __pass_to_client(expr, FUNCTION_CALL_HOOK); __inline_call = 0; if (inlinable(expr->fn)) { @@ -578,7 +595,7 @@ void __split_stmt(struct statement *stmt) sval_t sval; if (!stmt) - return; + goto out; if (out_of_memory() || __bail_on_rest_of_function) { static char *printed = NULL; @@ -599,15 +616,15 @@ void __split_stmt(struct statement *stmt) switch (stmt->type) { case STMT_DECLARATION: split_declaration(stmt->declaration); - return; + break; case STMT_RETURN: __split_expr(stmt->ret_value); __pass_to_client(stmt->ret_value, RETURN_HOOK); nullify_path(); - return; + break; case STMT_EXPRESSION: __split_expr(stmt->expression); - return; + break; case STMT_COMPOUND: { struct statement *tmp; @@ -618,28 +635,28 @@ void __split_stmt(struct statement *stmt) __split_stmt(tmp); } END_FOR_EACH_PTR(tmp); __call_scope_hooks(); - return; + break; } case STMT_IF: if (known_condition_true(stmt->if_conditional)) { __split_stmt(stmt->if_true); - return; + break; } if (known_condition_false(stmt->if_conditional)) { __split_stmt(stmt->if_false); - return; + break; } if (option_known_conditions && implied_condition_true(stmt->if_conditional)) { sm_info("this condition is true."); __split_stmt(stmt->if_true); - return; + break; } if (option_known_conditions && implied_condition_false(stmt->if_conditional)) { sm_info("this condition is false."); __split_stmt(stmt->if_false); - return; + break; } __split_whole_condition(stmt->if_conditional); __split_stmt(stmt->if_true); @@ -651,7 +668,7 @@ void __split_stmt(struct statement *stmt) __use_false_states(); __split_stmt(stmt->if_false); __merge_true_states(); - return; + break; case STMT_ITERATOR: if (stmt->iterator_pre_condition) handle_pre_loop(stmt); @@ -661,11 +678,11 @@ void __split_stmt(struct statement *stmt) // these are for(;;) type loops. handle_pre_loop(stmt); } - return; + break; case STMT_SWITCH: if (get_value(stmt->switch_expression, &sval)) { split_known_switch(stmt, sval); - return; + break; } __split_expr(stmt->switch_expression); push_expression(&switch_expr_stack, stmt->switch_expression); @@ -680,7 +697,7 @@ void __split_stmt(struct statement *stmt) __discard_switches(); __merge_breaks(); pop_expression(&switch_expr_stack); - return; + break; case STMT_CASE: __merge_switches(top_expression(switch_expr_stack), stmt->case_expression); @@ -691,7 +708,7 @@ void __split_stmt(struct statement *stmt) __split_expr(stmt->case_expression); __split_expr(stmt->case_to); __split_stmt(stmt->case_statement); - return; + break; case STMT_LABEL: if (stmt->label_identifier && stmt->label_identifier->type == SYM_LABEL && @@ -700,7 +717,7 @@ void __split_stmt(struct statement *stmt) __merge_gotos(stmt->label_identifier->ident->name); } __split_stmt(stmt->label_statement); - return; + break; case STMT_GOTO: __split_expr(stmt->goto_expression); if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) { @@ -716,24 +733,26 @@ void __split_stmt(struct statement *stmt) __save_gotos(stmt->goto_label->ident->name); } nullify_path(); - return; + break; case STMT_NONE: - return; + break; case STMT_ASM: __pass_to_client(stmt, ASM_HOOK); __split_expr(stmt->asm_string); split_asm_constraints(stmt->asm_outputs); split_asm_constraints(stmt->asm_inputs); split_asm_constraints(stmt->asm_clobbers); - return; + break; case STMT_CONTEXT: - return; + break; case STMT_RANGE: __split_expr(stmt->range_expression); __split_expr(stmt->range_low); __split_expr(stmt->range_high); - return; + break; } +out: + __process_post_op_stack(); } static void split_expr_list(struct expression_list *expr_list) @@ -742,6 +761,7 @@ static void split_expr_list(struct expression_list *expr_list) FOR_EACH_PTR(expr_list, expr) { __split_expr(expr); + __process_post_op_stack(); } END_FOR_EACH_PTR(expr); }