|
| 1 | +/*******************************************************************\ |
| 2 | +
|
| 3 | +Module: Show unused variables (including write only) |
| 4 | +
|
| 5 | +Author: Norbert Manthey [email protected] |
| 6 | +
|
| 7 | +\*******************************************************************/ |
| 8 | + |
| 9 | +#include <iostream> |
| 10 | +#include <cassert> |
| 11 | + |
| 12 | +#include <util/file_util.h> |
| 13 | +#include <util/prefix.h> |
| 14 | + |
| 15 | +#include <goto-instrument/rw_set.h> |
| 16 | +#include <pointer-analysis/value_set_analysis_fi.h> |
| 17 | +#include <analyses/dirty.h> |
| 18 | + |
| 19 | +#include "show_unused.h" |
| 20 | + |
| 21 | +/*******************************************************************\ |
| 22 | +
|
| 23 | +Function: show_unused |
| 24 | +
|
| 25 | + Inputs: symbol table, goto program |
| 26 | +
|
| 27 | + Outputs: prints list of variables that are never read |
| 28 | + returns false, if no unused variables have been found, |
| 29 | + else true |
| 30 | +
|
| 31 | + Purpose: help to spot variables that are never used globally in a |
| 32 | + program |
| 33 | +
|
| 34 | +\*******************************************************************/ |
| 35 | + |
| 36 | +bool show_unused( |
| 37 | + ui_message_handlert::uit ui, |
| 38 | + const symbol_tablet& symbol_table, |
| 39 | + const goto_functionst &goto_functions) |
| 40 | +{ |
| 41 | + const namespacet ns(symbol_table); |
| 42 | + rw_set_baset global_reads(ns); |
| 43 | + |
| 44 | + // get all symbols whose address is used |
| 45 | + dirtyt dirty_symbols(goto_functions); |
| 46 | + |
| 47 | + // compute for each function the set of read and written symbols |
| 48 | + forall_goto_functions(it, goto_functions) |
| 49 | + { |
| 50 | + if(!it->second.body_available()) |
| 51 | + continue; |
| 52 | + |
| 53 | + if(!symbol_table.has_symbol(it->first)) |
| 54 | + { |
| 55 | + std::cerr << " warning: did not find symbol for: " |
| 56 | + << id2string(it->first) << std::endl; |
| 57 | + continue; |
| 58 | + } |
| 59 | + symbolt symbol=symbol_table.lookup(it->first); |
| 60 | + |
| 61 | + value_set_analysis_fit value_sets(ns); |
| 62 | + rw_set_functiont rw_set( |
| 63 | + value_sets, |
| 64 | + ns, |
| 65 | + goto_functions, |
| 66 | + symbol.symbol_expr()); |
| 67 | + global_reads+=rw_set; |
| 68 | + } |
| 69 | + |
| 70 | + // check the symbol table against the global_reads set, collect unused symbols |
| 71 | + std::vector<std::pair<const dstring, symbolt> > actual_unused_symbols; |
| 72 | + forall_symbols(it, symbol_table.symbols) |
| 73 | + { |
| 74 | + // we are not interested in functions that are not read |
| 75 | + if(it->second.type.id()==ID_code) |
| 76 | + continue; |
| 77 | + |
| 78 | + // skip internal, anonymous symbols, and if no location is present |
| 79 | + if(has_prefix(id2string(it->second.name), "__CPROVER")) |
| 80 | + continue; |
| 81 | + if(has_prefix(id2string(it->second.base_name), "#anon")) |
| 82 | + continue; |
| 83 | + if(it->second.location.as_string().empty()) |
| 84 | + continue; |
| 85 | + |
| 86 | + if(!global_reads.has_r_entry(it->second.name) && |
| 87 | + dirty_symbols.get_dirty_ids().find(it->second.name)== |
| 88 | + dirty_symbols.get_dirty_ids().end()) |
| 89 | + { |
| 90 | + actual_unused_symbols.push_back(*it); |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + // print collected symbols |
| 95 | + switch(ui) |
| 96 | + { |
| 97 | + case ui_message_handlert::PLAIN: |
| 98 | + std::cerr << "found " << actual_unused_symbols.size() |
| 99 | + << " symbols to report" << std::endl; |
| 100 | + for(auto it=actual_unused_symbols.begin(); |
| 101 | + it!=actual_unused_symbols.end(); ++it) |
| 102 | + { |
| 103 | + const source_locationt &location=it->second.location; |
| 104 | + std::cout |
| 105 | + << concat_dir_file( |
| 106 | + id2string(location.get_working_directory()), |
| 107 | + id2string(location.get_file())) |
| 108 | + << ":" << id2string(location.get_line()) |
| 109 | + << " variable " << id2string(it->second.base_name) |
| 110 | + << " is never read" << std::endl; |
| 111 | + } |
| 112 | + break; |
| 113 | + default: |
| 114 | + assert(false && "chosen UI is not yet implemented"); |
| 115 | + } |
| 116 | + return 0; |
| 117 | +} |
| 118 | + |
0 commit comments