1*1f5207b7SJohn Levon /* 2*1f5207b7SJohn Levon * Copyright (C) 2016 Oracle. 3*1f5207b7SJohn Levon * 4*1f5207b7SJohn Levon * This program is free software; you can redistribute it and/or 5*1f5207b7SJohn Levon * modify it under the terms of the GNU General Public License 6*1f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2 7*1f5207b7SJohn Levon * of the License, or (at your option) any later version. 8*1f5207b7SJohn Levon * 9*1f5207b7SJohn Levon * This program is distributed in the hope that it will be useful, 10*1f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*1f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*1f5207b7SJohn Levon * GNU General Public License for more details. 13*1f5207b7SJohn Levon * 14*1f5207b7SJohn Levon * You should have received a copy of the GNU General Public License 15*1f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt 16*1f5207b7SJohn Levon */ 17*1f5207b7SJohn Levon 18*1f5207b7SJohn Levon #include "smatch.h" 19*1f5207b7SJohn Levon 20*1f5207b7SJohn Levon static struct statement_list *stmt_list; 21*1f5207b7SJohn Levon end_of_function(struct statement * stmt)22*1f5207b7SJohn Levonstatic int end_of_function(struct statement *stmt) 23*1f5207b7SJohn Levon { 24*1f5207b7SJohn Levon struct symbol *fn = get_base_type(cur_func_sym); 25*1f5207b7SJohn Levon 26*1f5207b7SJohn Levon /* err on the conservative side of things */ 27*1f5207b7SJohn Levon if (!fn) 28*1f5207b7SJohn Levon return 1; 29*1f5207b7SJohn Levon if (stmt == fn->stmt || stmt == fn->inline_stmt) 30*1f5207b7SJohn Levon return 1; 31*1f5207b7SJohn Levon return 0; 32*1f5207b7SJohn Levon } 33*1f5207b7SJohn Levon 34*1f5207b7SJohn Levon /* 35*1f5207b7SJohn Levon * We're wasting a lot of time worrying about out of scope variables. 36*1f5207b7SJohn Levon * When we come to the end of a scope then just delete them all the out of 37*1f5207b7SJohn Levon * scope states. 38*1f5207b7SJohn Levon */ match_end_of_block(struct statement * stmt)39*1f5207b7SJohn Levonstatic void match_end_of_block(struct statement *stmt) 40*1f5207b7SJohn Levon { 41*1f5207b7SJohn Levon struct statement *tmp; 42*1f5207b7SJohn Levon struct symbol *sym; 43*1f5207b7SJohn Levon 44*1f5207b7SJohn Levon if (end_of_function(stmt)) 45*1f5207b7SJohn Levon return; 46*1f5207b7SJohn Levon 47*1f5207b7SJohn Levon FOR_EACH_PTR(stmt->stmts, tmp) { 48*1f5207b7SJohn Levon if (tmp->type != STMT_DECLARATION) 49*1f5207b7SJohn Levon return; 50*1f5207b7SJohn Levon 51*1f5207b7SJohn Levon FOR_EACH_PTR(tmp->declaration, sym) { 52*1f5207b7SJohn Levon if (!sym->ident) 53*1f5207b7SJohn Levon continue; 54*1f5207b7SJohn Levon __delete_all_states_sym(sym); 55*1f5207b7SJohn Levon } END_FOR_EACH_PTR(sym); 56*1f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 57*1f5207b7SJohn Levon } 58*1f5207b7SJohn Levon is_outer_stmt(struct statement * stmt)59*1f5207b7SJohn Levonstatic int is_outer_stmt(struct statement *stmt) 60*1f5207b7SJohn Levon { 61*1f5207b7SJohn Levon struct symbol *fn; 62*1f5207b7SJohn Levon 63*1f5207b7SJohn Levon if (!cur_func_sym) 64*1f5207b7SJohn Levon return 0; 65*1f5207b7SJohn Levon fn = get_base_type(cur_func_sym); 66*1f5207b7SJohn Levon if (!fn) 67*1f5207b7SJohn Levon return 0; 68*1f5207b7SJohn Levon /* 69*1f5207b7SJohn Levon * There are times when ->parent is not set but it's set for 70*1f5207b7SJohn Levon * the outer statement so ignoring NULLs works as a work-around. 71*1f5207b7SJohn Levon */ 72*1f5207b7SJohn Levon if (!stmt->parent) 73*1f5207b7SJohn Levon return 0; 74*1f5207b7SJohn Levon if (stmt->parent == fn->stmt || 75*1f5207b7SJohn Levon stmt->parent == fn->inline_stmt) 76*1f5207b7SJohn Levon return 1; 77*1f5207b7SJohn Levon return 0; 78*1f5207b7SJohn Levon } 79*1f5207b7SJohn Levon match_stmt(struct statement * stmt)80*1f5207b7SJohn Levonstatic void match_stmt(struct statement *stmt) 81*1f5207b7SJohn Levon { 82*1f5207b7SJohn Levon struct statement *tmp; 83*1f5207b7SJohn Levon 84*1f5207b7SJohn Levon if (__inline_fn) 85*1f5207b7SJohn Levon return; 86*1f5207b7SJohn Levon 87*1f5207b7SJohn Levon if (stmt->type == STMT_COMPOUND) 88*1f5207b7SJohn Levon add_ptr_list(&stmt_list, stmt); 89*1f5207b7SJohn Levon 90*1f5207b7SJohn Levon if (!is_outer_stmt(stmt)) 91*1f5207b7SJohn Levon return; 92*1f5207b7SJohn Levon 93*1f5207b7SJohn Levon FOR_EACH_PTR(stmt_list, tmp) { 94*1f5207b7SJohn Levon match_end_of_block(tmp); 95*1f5207b7SJohn Levon } END_FOR_EACH_PTR(tmp); 96*1f5207b7SJohn Levon free_ptr_list(&stmt_list); 97*1f5207b7SJohn Levon } 98*1f5207b7SJohn Levon match_end_func(struct symbol * sym)99*1f5207b7SJohn Levonstatic void match_end_func(struct symbol *sym) 100*1f5207b7SJohn Levon { 101*1f5207b7SJohn Levon if (__inline_fn) 102*1f5207b7SJohn Levon return; 103*1f5207b7SJohn Levon free_ptr_list(&stmt_list); 104*1f5207b7SJohn Levon } 105*1f5207b7SJohn Levon register_scope(int id)106*1f5207b7SJohn Levonvoid register_scope(int id) 107*1f5207b7SJohn Levon { 108*1f5207b7SJohn Levon add_hook(&match_stmt, STMT_HOOK_AFTER); 109*1f5207b7SJohn Levon add_hook(&match_end_func, AFTER_FUNC_HOOK); 110*1f5207b7SJohn Levon } 111