diff --git a/jbmc/src/java_bytecode/java_local_variable_table.cpp b/jbmc/src/java_bytecode/java_local_variable_table.cpp index ce3ee7934a3..c7fde311bd0 100644 --- a/jbmc/src/java_bytecode/java_local_variable_table.cpp +++ b/jbmc/src/java_bytecode/java_local_variable_table.cpp @@ -32,6 +32,10 @@ struct procedure_local_cfg_baset< : public grapht< cfg_base_nodet> { + typedef grapht< + cfg_base_nodet> + base_grapht; + typedef typename base_grapht::nodet nodet; typedef java_bytecode_convert_methodt::method_with_amapt method_with_amapt; typedef std::map @@ -85,6 +89,23 @@ struct procedure_local_cfg_baset< } } + java_bytecode_convert_methodt::method_offsett get_node_index( + const java_bytecode_convert_methodt::method_offsett &instruction) const + { + return entry_map.at(instruction); + } + + nodet & + get_node(const java_bytecode_convert_methodt::method_offsett &instruction) + { + return (*this)[get_node_index(instruction)]; + } + const nodet &get_node( + const java_bytecode_convert_methodt::method_offsett &instruction) const + { + return (*this)[get_node_index(instruction)]; + } + static java_bytecode_convert_methodt::method_offsett get_first_node(const method_with_amapt &args) { diff --git a/src/analyses/cfg_dominators.h b/src/analyses/cfg_dominators.h index 2b7c052692b..de50f48f568 100644 --- a/src/analyses/cfg_dominators.h +++ b/src/analyses/cfg_dominators.h @@ -53,14 +53,14 @@ class cfg_dominators_templatet /// for \p program_point const typename cfgt::nodet &get_node(const T &program_point) const { - return cfg[cfg.entry_map.at(program_point)]; + return cfg.get_node(program_point); } /// Get the graph node (which gives dominators, predecessors and successors) /// for \p program_point typename cfgt::nodet &get_node(const T &program_point) { - return cfg[cfg.entry_map.at(program_point)]; + return cfg.get_node(program_point); } /// Returns true if the program point corresponding to \p rhs_node is @@ -149,7 +149,7 @@ void cfg_dominators_templatet::fixedpoint(P &program) entry_node = cfgt::get_last_node(program); else entry_node = cfgt::get_first_node(program); - typename cfgt::nodet &n=cfg[cfg.entry_map[entry_node]]; + typename cfgt::nodet &n = cfg.get_node(entry_node); n.dominators.insert(entry_node); for(typename cfgt::edgest::const_iterator @@ -165,7 +165,7 @@ void cfg_dominators_templatet::fixedpoint(P &program) worklist.pop_front(); bool changed=false; - typename cfgt::nodet &node=cfg[cfg.entry_map[current]]; + typename cfgt::nodet &node = cfg.get_node(current); if(node.dominators.empty()) { for(const auto &edge : (post_dom ? node.out : node.in)) @@ -248,7 +248,7 @@ inline void dominators_pretty_print_node( template void cfg_dominators_templatet::output(std::ostream &out) const { - for(const auto &node : cfg.entry_map) + for(const auto &node : cfg.entries()) { auto n=node.first; diff --git a/src/goto-diff/change_impact.cpp b/src/goto-diff/change_impact.cpp index 21ac912065e..6dced75e578 100644 --- a/src/goto-diff/change_impact.cpp +++ b/src/goto-diff/change_impact.cpp @@ -66,27 +66,26 @@ void full_slicert::operator()( // declarations or dead instructions may be necessary as well decl_deadt decl_dead; - for(cfgt::entry_mapt::iterator - e_it=cfg.entry_map.begin(); - e_it!=cfg.entry_map.end(); - e_it++) + for(const auto &entry : cfg.entries()) { - if(criterion(e_it->first)) - add_to_queue(queue, e_it->second, e_it->first); - else if(implicit(e_it->first)) - add_to_queue(queue, e_it->second, e_it->first); - else if((e_it->first->is_goto() && e_it->first->guard.is_true()) || - e_it->first->is_throw()) - jumps.push_back(e_it->second); - else if(e_it->first->is_decl()) + const auto &instruction = instruction_and_index.first; + const auto instruction_node_index = instruction_and_index.second; + if(criterion(instruction)) + add_to_queue(queue, instruction_node_index, instruction); + else if(implicit(instruction)) + add_to_queue(queue, instruction_node_index, instruction); + else if((instruction->is_goto() && instruction->guard.is_true()) || + instruction->is_throw()) + jumps.push_back(instruction_node_index); + else if(instruction->is_decl()) { - const auto &s=to_code_decl(e_it->first->code).symbol(); - decl_dead[s.get_identifier()].push(e_it->second); + const auto &s=to_code_decl(instruction->code).symbol(); + decl_dead[s.get_identifier()].push(instruction_node_index); } - else if(e_it->first->is_dead()) + else if(instruction->is_dead()) { - const auto &s=to_code_dead(e_it->first->code).symbol(); - decl_dead[s.get_identifier()].push(e_it->second); + const auto &s=to_code_dead(instruction->code).symbol(); + decl_dead[s.get_identifier()].push(instruction_node_index); } } @@ -105,9 +104,9 @@ void full_slicert::operator()( { Forall_goto_program_instructions(i_it, f_it->second.body) { - const cfgt::entryt &e=cfg.entry_map[i_it]; + const auto &node = cfg.get_node(i_it); if(!i_it->is_end_function() && // always retained - !cfg[e].node_required) + !node.node_required) i_it->make_skip(); #ifdef DEBUG_FULL_SLICERT else @@ -115,11 +114,11 @@ void full_slicert::operator()( std::string c="ins:"+std::to_string(i_it->location_number); c+=" req by:"; for(std::set::const_iterator - req_it=cfg[e].required_by.begin(); - req_it!=cfg[e].required_by.end(); + req_it=node.required_by.begin(); + req_it!=node.required_by.end(); ++req_it) { - if(req_it!=cfg[e].required_by.begin()) + if(req_it!=node.required_by.begin()) c+=","; c+=std::to_string(*req_it); } @@ -144,13 +143,10 @@ void full_slicert::fixedpoint( { std::vector dep_node_to_cfg; dep_node_to_cfg.reserve(dep_graph.size()); + for(unsigned i=0; isecond); + dep_node_to_cfg.push_back(cfg.get_node_index(dep_graph[i].PC)); } // process queue until empty diff --git a/src/goto-instrument/count_eloc.cpp b/src/goto-instrument/count_eloc.cpp index 33bb6519585..98e50224ae0 100644 --- a/src/goto-instrument/count_eloc.cpp +++ b/src/goto-instrument/count_eloc.cpp @@ -106,10 +106,10 @@ void print_path_lengths(const goto_modelt &goto_model) const goto_programt &start_program=start->second.body; - const cfgt::entryt &start_node= - cfg.entry_map[start_program.instructions.begin()]; - const cfgt::entryt &last_node= - cfg.entry_map[--start_program.instructions.end()]; + const cfgt::entryt &start_node = + cfg.get_node_index(start_program.instructions.begin()); + const cfgt::entryt &last_node = + cfg.get_node_index(--start_program.instructions.end()); cfgt::patht shortest_path; cfg.shortest_path(start_node, last_node, shortest_path); @@ -123,7 +123,7 @@ void print_path_lengths(const goto_modelt &goto_model) if(i_it->is_backwards_goto() || i_it==gf_it->second.body.instructions.begin()) { - const cfgt::entryt &node=cfg.entry_map[i_it]; + const cfgt::entryt &node = cfg.get_node_index(i_it); cfgt::patht loop; cfg.shortest_loop(node, loop); diff --git a/src/goto-instrument/full_slicer.cpp b/src/goto-instrument/full_slicer.cpp index e04c59257d8..d034045d2e5 100644 --- a/src/goto-instrument/full_slicer.cpp +++ b/src/goto-instrument/full_slicer.cpp @@ -46,15 +46,9 @@ void full_slicert::add_function_calls( goto_programt::const_targett begin_function= f_it->second.body.instructions.begin(); - cfgt::entry_mapt::const_iterator entry= - cfg.entry_map.find(begin_function); - assert(entry!=cfg.entry_map.end()); - - for(cfgt::edgest::const_iterator - it=cfg[entry->second].in.begin(); - it!=cfg[entry->second].in.end(); - ++it) - add_to_queue(queue, it->first, node.PC); + const auto &entry = cfg.get_node(begin_function); + for(const auto &in_edge : entry.in) + add_to_queue(queue, in_edge.first, node.PC); } void full_slicert::add_decl_dead( @@ -135,11 +129,7 @@ void full_slicert::add_jumps( goto_programt::const_targett lex_succ=j.PC; for( ; !lex_succ->is_end_function(); ++lex_succ) { - cfgt::entry_mapt::const_iterator entry= - cfg.entry_map.find(lex_succ); - assert(entry!=cfg.entry_map.end()); - - if(cfg[entry->second].node_required) + if(cfg.get_node(lex_succ).node_required) break; } if(lex_succ->is_end_function()) @@ -170,13 +160,10 @@ void full_slicert::add_jumps( d_it != j_PC_node.dominators.end(); ++d_it) { - cfgt::entry_mapt::const_iterator entry= - cfg.entry_map.find(*d_it); - assert(entry!=cfg.entry_map.end()); - - if(cfg[entry->second].node_required) + const auto &node = cfg.get_node(*d_it); + if(node.node_required) { - const irep_idt &id2 = cfg[entry->second].function_id; + const irep_idt &id2 = node.function_id; INVARIANT(id==id2, "goto/jump expected to be within a single function"); @@ -209,14 +196,9 @@ void full_slicert::fixedpoint( { std::vector dep_node_to_cfg; dep_node_to_cfg.reserve(dep_graph.size()); - for(dependence_grapht::node_indext i=0; isecond); - } + for(dependence_grapht::node_indext i = 0; i < dep_graph.size(); ++i) + dep_node_to_cfg.push_back(cfg.get_node_index(dep_graph[i].PC)); // process queue until empty while(!queue.empty()) @@ -279,7 +261,7 @@ void full_slicert::operator()( forall_goto_functions(f_it, goto_functions) { forall_goto_program_instructions(i_it, f_it->second.body) - cfg[cfg.entry_map[i_it]].function_id = f_it->first; + cfg.get_node(i_it).function_id = f_it->first; } // fill queue with according to slicing criterion @@ -289,28 +271,27 @@ void full_slicert::operator()( // declarations or dead instructions may be necessary as well decl_deadt decl_dead; - for(cfgt::entry_mapt::iterator - e_it=cfg.entry_map.begin(); - e_it!=cfg.entry_map.end(); - e_it++) + for(const auto &instruction_and_index : cfg.entries()) { - if(criterion(cfg[e_it->second].function_id, e_it->first)) - add_to_queue(queue, e_it->second, e_it->first); - else if(implicit(e_it->first)) - add_to_queue(queue, e_it->second, e_it->first); + const auto &instruction = instruction_and_index.first; + const auto instruction_node_index = instruction_and_index.second; + if(criterion(cfg[instruction_node_index].function_id, instruction)) + add_to_queue(queue, instruction_node_index, instruction); + else if(implicit(instruction)) + add_to_queue(queue, instruction_node_index, instruction); else if( - (e_it->first->is_goto() && e_it->first->get_condition().is_true()) || - e_it->first->is_throw()) - jumps.push_back(e_it->second); - else if(e_it->first->is_decl()) + (instruction->is_goto() && instruction->get_condition().is_true()) || + instruction->is_throw()) + jumps.push_back(instruction_node_index); + else if(instruction->is_decl()) { - const auto &s = to_code_decl(e_it->first->code).symbol(); - decl_dead[s.get_identifier()].push(e_it->second); + const auto &s = to_code_decl(instruction->code).symbol(); + decl_dead[s.get_identifier()].push(instruction_node_index); } - else if(e_it->first->is_dead()) + else if(instruction->is_dead()) { - const auto &s = to_code_dead(e_it->first->code).symbol(); - decl_dead[s.get_identifier()].push(e_it->second); + const auto &s = to_code_dead(instruction->code).symbol(); + decl_dead[s.get_identifier()].push(instruction_node_index); } } @@ -329,9 +310,10 @@ void full_slicert::operator()( { Forall_goto_program_instructions(i_it, f_it->second.body) { - const cfgt::entryt &e=cfg.entry_map[i_it]; - if(!i_it->is_end_function() && // always retained - !cfg[e].node_required) + const auto &cfg_node = cfg.get_node(i_it); + if( + !i_it->is_end_function() && // always retained + !cfg_node.node_required) { i_it->turn_into_skip(); } @@ -340,12 +322,12 @@ void full_slicert::operator()( { std::string c="ins:"+std::to_string(i_it->location_number); c+=" req by:"; - for(std::set::const_iterator - req_it=cfg[e].required_by.begin(); - req_it!=cfg[e].required_by.end(); + for(std::set::const_iterator req_it = + cfg_node.required_by.begin(); + req_it != cfg_node.required_by.end(); ++req_it) { - if(req_it!=cfg[e].required_by.begin()) + if(req_it != cfg_node.required_by.begin()) c+=","; c+=std::to_string(*req_it); } diff --git a/src/goto-instrument/points_to.cpp b/src/goto-instrument/points_to.cpp index 5b79d8382b8..237590b881b 100644 --- a/src/goto-instrument/points_to.cpp +++ b/src/goto-instrument/points_to.cpp @@ -21,12 +21,9 @@ void points_tot::fixedpoint() { added=false; - for(cfgt::entry_mapt::iterator - e_it=cfg.entry_map.begin(); - e_it!=cfg.entry_map.end(); - e_it++) + for(const auto &instruction_and_entry : cfg.entries()) { - if(transform(cfg[e_it->second])) + if(transform(cfg[instruction_and_entry.second])) added=true; } } diff --git a/src/goto-instrument/reachability_slicer.cpp b/src/goto-instrument/reachability_slicer.cpp index 3f9a87fb24e..18b2e1c323a 100644 --- a/src/goto-instrument/reachability_slicer.cpp +++ b/src/goto-instrument/reachability_slicer.cpp @@ -39,7 +39,7 @@ reachability_slicert::get_sources( const slicing_criteriont &criterion) { std::vector sources; - for(const auto &e_it : cfg.entry_map) + for(const auto &e_it : cfg.entries()) { if( criterion(cfg[e_it.second].function_id, e_it.first) || @@ -64,12 +64,9 @@ bool reachability_slicert::is_same_target( { // Avoid comparing iterators belonging to different functions, and therefore // different std::lists. - cfgt::entry_mapt::const_iterator it1_entry = cfg.entry_map.find(it1); - cfgt::entry_mapt::const_iterator it2_entry = cfg.entry_map.find(it2); - return it1_entry != cfg.entry_map.end() && it2_entry != cfg.entry_map.end() && - cfg[it1_entry->second].function_id == - cfg[it2_entry->second].function_id && - it1 == it2; + const auto &node1 = cfg.get_node(it1); + const auto &node2 = cfg.get_node(it2); + return node1.function_id == node2.function_id && it1 == it2; } /// Perform backward depth-first search of the control-flow graph of the @@ -108,7 +105,7 @@ reachability_slicert::backward_outwards_walk_from( "all function return edges should point to the successor of a " "FUNCTION_CALL instruction"); - stack.push_back(cfg.entry_map[std::prev(node.PC)]); + stack.push_back(cfg.get_node_index(std::prev(node.PC))); } else { @@ -157,7 +154,7 @@ void reachability_slicert::backward_inwards_walk_from( "all function return edges should point to the successor of a " "FUNCTION_CALL instruction"); - stack.push_back(cfg.entry_map[std::prev(node.PC)]); + stack.push_back(cfg.get_node_index(std::prev(node.PC))); } else if(pred_node.PC->is_function_call()) { @@ -223,8 +220,9 @@ void reachability_slicert::forward_walk_call_instruction( while(!successor_pc->is_end_function()) ++successor_pc; - if(!cfg[cfg.entry_map[successor_pc]].out.empty()) - callsite_successor_stack.push_back(cfg.entry_map[callsite_successor_pc]); + if(!cfg.get_node(successor_pc).out.empty()) + callsite_successor_stack.push_back( + cfg.get_node_index(callsite_successor_pc)); } else { @@ -343,7 +341,7 @@ void reachability_slicert::slice(goto_functionst &goto_functions) { Forall_goto_program_instructions(i_it, f_it->second.body) { - cfgt::nodet &e = cfg[cfg.entry_map[i_it]]; + cfgt::nodet &e = cfg.get_node(i_it); if( !e.reaches_assertion && !e.reachable_from_assertion && !i_it->is_end_function()) diff --git a/src/goto-programs/cfg.h b/src/goto-programs/cfg.h index d085463cb37..cfeb28ce892 100644 --- a/src/goto-programs/cfg.h +++ b/src/goto-programs/cfg.h @@ -61,8 +61,11 @@ template class cfg_baset:public grapht< cfg_base_nodet > { + typedef grapht> base_grapht; + public: - typedef std::size_t entryt; + typedef typename base_grapht::node_indext entryt; + typedef typename base_grapht::nodet nodet; class entry_mapt final { @@ -73,9 +76,9 @@ class cfg_baset:public grapht< cfg_base_nodet > grapht< cfg_base_nodet > &container; // NOLINTNEXTLINE(readability/identifiers) - typedef data_typet::iterator iterator; + typedef typename data_typet::iterator iterator; // NOLINTNEXTLINE(readability/identifiers) - typedef data_typet::const_iterator const_iterator; + typedef typename data_typet::const_iterator const_iterator; template const_iterator find(U &&u) const { return data.find(std::forward(u)); } @@ -179,6 +182,36 @@ class cfg_baset:public grapht< cfg_base_nodet > compute_edges(goto_functions, goto_program); } + /// Get the graph node index for \p program_point. Use this with operator[] + /// to get the related graph node (e.g. `cfg[cfg.get_node_index(i)]`, though + /// in that particular case you should just use `cfg.get_node(i)`). Storing + /// node indices saves a map lookup, so it can be worthwhile when you expect + /// to repeatedly look up the same program point. + entryt get_node_index(const I &program_point) const + { + return entry_map.at(program_point); + } + + /// Get the CFG graph node relating to \p program_point. + nodet &get_node(const I &program_point) + { + return (*this)[get_node_index(program_point)]; + } + + /// Get the CFG graph node relating to \p program_point. + const nodet &get_node(const I &program_point) const + { + return (*this)[get_node_index(program_point)]; + } + + /// Get a map from program points to their corresponding node indices. Use + /// the indices with `operator[]` similar to those returned by + /// \ref get_node_index. + const entry_mapt &entries() const + { + return entry_map; + } + static I get_first_node(P &program) { return program.instructions.begin();