Skip to content

Commit

Permalink
Merge pull request diffblue#2053 from owen-jones-diffblue/owen-jones-…
Browse files Browse the repository at this point in the history
…diffblue/bugfix/make-callgraph-include-uncalled-functions

Make directed callgraph include nodes with no edges
  • Loading branch information
smowton authored Apr 19, 2018
2 parents de1915a + d73f6bc commit b7ef5af
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 19 deletions.
81 changes: 81 additions & 0 deletions regression/goto-instrument/call-graph1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@

int x;

void func0()
{
func0();
}

void func1()
{
x = 1;
}

void func2()
{
x = 2;
func3();
}

void func3()
{
x = 3;
}

void func4(int b)
{
x = 4;
if(b)
{
func5(0);
}
}

void func5(int b)
{
x = 5;
func4(b);
}

void func6()
{
x = 6;
}

void func7(int b)
{
x = 7;
if(b)
{
func8(0);
}
}

void func8(int b)
{
x = 8;
func7(b);
}

void func9()
{
x = 9;
funca();
}

void funca()
{
x = 10;
func9();
}



int main()
{
func1();
func2();
func4(1);

return 0;
}
20 changes: 20 additions & 0 deletions regression/goto-instrument/call-graph1/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CORE
main.c
--call-graph
^EXIT=0$
^SIGNAL=0$
^main -> func2$
^main -> func1$
^main -> func4$
^funca -> func9$
^func9 -> funca$
^func8 -> func7$
^func7 -> func8$
^__CPROVER__start -> __CPROVER_initialize$
^__CPROVER__start -> main$
^func2 -> func3$
^func0 -> func0$
^func4 -> func5$
^func5 -> func4$
--
^warning: ignoring
81 changes: 81 additions & 0 deletions regression/goto-instrument/reachable-call-graph1/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@

int x;

void func0()
{
func0();
}

void func1()
{
x = 1;
}

void func2()
{
x = 2;
func3();
}

void func3()
{
x = 3;
}

void func4(int b)
{
x = 4;
if(b)
{
func5(0);
}
}

void func5(int b)
{
x = 5;
func4(b);
}

void func6()
{
x = 6;
}

void func7(int b)
{
x = 7;
if(b)
{
func8(0);
}
}

void func8(int b)
{
x = 8;
func7(b);
}

void func9()
{
x = 9;
funca();
}

void funca()
{
x = 10;
func9();
}



int main()
{
func1();
func2();
func4(1);

return 0;
}
20 changes: 20 additions & 0 deletions regression/goto-instrument/reachable-call-graph1/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CORE
main.c
--reachable-call-graph
^EXIT=0$
^SIGNAL=0$
^main -> func2$
^main -> func1$
^main -> func4$
^__CPROVER__start -> __CPROVER_initialize$
^__CPROVER__start -> main$
^func2 -> func3$
^func4 -> func5$
^func5 -> func4$
--
^funca -> func9$
^func9 -> funca$
^func8 -> func7$
^func7 -> func8$
^func0 -> func0$
^warning: ignoring
30 changes: 21 additions & 9 deletions src/analyses/call_graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ call_grapht::call_grapht(
{
forall_goto_functions(f_it, goto_functions)
{
const goto_programt &body=f_it->second.body;
add(f_it->first, body);
const irep_idt &function_name = f_it->first;
const goto_programt &body = f_it->second.body;
nodes.insert(function_name);
add(function_name, body);
}
}

Expand Down Expand Up @@ -84,12 +86,14 @@ call_grapht::call_grapht(
const goto_programt &goto_program=
goto_functions.function_map.at(function).body;

nodes.insert(function);

forall_callsites(
goto_program,
[&](goto_programt::const_targett i_it, const irep_idt &callee)
{
add(function, callee, i_it);
if(graph.find(callee)==graph.end())
if(edges.find(callee)==edges.end())
pending_stack.push(callee);
}
); // NOLINT
Expand Down Expand Up @@ -129,7 +133,9 @@ void call_grapht::add(
const irep_idt &caller,
const irep_idt &callee)
{
graph.insert(std::pair<irep_idt, irep_idt>(caller, callee));
edges.insert({caller, callee});
nodes.insert(caller);
nodes.insert(callee);
}

/// Add edge with optional callsite information
Expand All @@ -152,7 +158,8 @@ void call_grapht::add(
call_grapht call_grapht::get_inverted() const
{
call_grapht result;
for(const auto &caller_callee : graph)
result.nodes = nodes;
for(const auto &caller_callee : edges)
result.add(caller_callee.second, caller_callee.first);
return result;
}
Expand Down Expand Up @@ -197,7 +204,12 @@ call_grapht::directed_grapht call_grapht::get_directed_graph() const
call_grapht::directed_grapht ret;
function_indicest function_indices(ret);

for(const auto &edge : graph)
// To make sure we include unreachable functions we first create indices
// for all nodes in the graph
for(const irep_idt &function_name : nodes)
function_indices[function_name];

for(const auto &edge : edges)
{
auto a_index=function_indices[edge.first];
auto b_index=function_indices[edge.second];
Expand Down Expand Up @@ -237,7 +249,7 @@ void call_grapht::output_dot(std::ostream &out) const
{
out << "digraph call_graph {\n";

for(const auto &edge : graph)
for(const auto &edge : edges)
{
out << " \"" << edge.first << "\" -> "
<< "\"" << edge.second << "\" "
Expand All @@ -252,7 +264,7 @@ void call_grapht::output_dot(std::ostream &out) const

void call_grapht::output(std::ostream &out) const
{
for(const auto &edge : graph)
for(const auto &edge : edges)
{
out << edge.first << " -> " << edge.second << "\n";
if(collect_callsites)
Expand All @@ -267,7 +279,7 @@ void call_grapht::output_xml(std::ostream &out) const
if(collect_callsites)
out << "<!-- XML call-graph representation does not document callsites yet."
" If you need this, edit call_grapht::output_xml -->\n";
for(const auto &edge : graph)
for(const auto &edge : edges)
{
out << "<call_graph_edge caller=\"";
xmlt::escape_attribute(id2string(edge.first), out);
Expand Down
14 changes: 9 additions & 5 deletions src/analyses/call_graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,14 @@ class call_grapht
void output(std::ostream &out) const;
void output_xml(std::ostream &out) const;

/// Type of the call graph. Note parallel edges (e.g. A having two callsites
/// both targeting B) result in multiple graph edges.
typedef std::multimap<irep_idt, irep_idt> grapht;
/// Type of the nodes in the call graph.
typedef std::unordered_set<irep_idt, irep_id_hash> nodest;

/// Type of a call graph edge in `grapht`
/// Type of the edges in the call graph. Note parallel edges (e.g. A having
/// two callsites both targeting B) result in multiple graph edges.
typedef std::multimap<irep_idt, irep_idt> edgest;

/// Type of a call graph edge in `edgest`
typedef std::pair<irep_idt, irep_idt> edget;

/// Type of a callsite stored in member `callsites`
Expand All @@ -84,7 +87,8 @@ class call_grapht
/// backward compatibility; use `get_directed_graph()` to get a generic
/// directed graph representation that provides more graph algorithms
/// (shortest path, SCCs and so on).
grapht graph;
edgest edges;
nodest nodes;

/// Map from call-graph edges to a set of callsites that make the given call.
callsitest callsites;
Expand Down
Loading

0 comments on commit b7ef5af

Please sign in to comment.