flow: handle POST_OPs correctly
authorDan Carpenter <dan.carpenter@oracle.com>
Fri, 15 Mar 2013 19:54:32 +0000 (15 22:54 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Fri, 15 Mar 2013 19:54:32 +0000 (15 22:54 +0300)
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 <dan.carpenter@oracle.com>
smatch.h
smatch_conditions.c
smatch_flow.c

index e1f2ed5..38274ab 100644 (file)
--- 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;
index 6684e08..9450d3d 100644 (file)
@@ -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);
 }
 
index 7e86c28..8d41cc6 100644 (file)
@@ -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);
 }