Skip to content

Commit a1a972f

Browse files
authored
Merge pull request diffblue#1776 from smowton/smowton/feature/class-hierarchy-grapht
Add class-hierarchy variant based on grapht
2 parents ef3c598 + a6eed7c commit a1a972f

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed

src/goto-programs/class_hierarchy.cpp

+35
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,41 @@ void class_hierarchyt::operator()(const symbol_tablet &symbol_table)
4747
}
4848
}
4949

50+
/// Populate the class hierarchy graph, such that there is a node for every
51+
/// struct type in the symbol table and an edge representing each superclass
52+
/// <-> subclass relationship, pointing from parent to child.
53+
/// \param symbol_table: global symbol table, which will be searched for struct
54+
/// types.
55+
void class_hierarchy_grapht::populate(const symbol_tablet &symbol_table)
56+
{
57+
// Add nodes for all classes:
58+
forall_symbols(it, symbol_table.symbols)
59+
{
60+
if(it->second.is_type && it->second.type.id() == ID_struct)
61+
{
62+
node_indext new_node_index = add_node();
63+
nodes_by_name[it->first] = new_node_index;
64+
(*this)[new_node_index].class_identifier = it->first;
65+
}
66+
}
67+
68+
// Add parent -> child edges:
69+
forall_symbols(it, symbol_table.symbols)
70+
{
71+
if(it->second.is_type && it->second.type.id() == ID_struct)
72+
{
73+
const class_typet &class_type = to_class_type(it->second.type);
74+
75+
for(const auto &base : class_type.bases())
76+
{
77+
const irep_idt &parent = to_symbol_type(base.type()).get_identifier();
78+
if(!parent.empty())
79+
add_edge(nodes_by_name.at(parent), nodes_by_name.at(it->first));
80+
}
81+
}
82+
}
83+
}
84+
5085
void class_hierarchyt::get_children_trans_rec(
5186
const irep_idt &c,
5287
idst &dest) const

src/goto-programs/class_hierarchy.h

+32
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Date: April 2016
1717
#include <iosfwd>
1818
#include <map>
1919

20+
#include <util/graph.h>
2021
#include <util/namespace.h>
2122

2223
class class_hierarchyt
@@ -59,4 +60,35 @@ class class_hierarchyt
5960
void get_parents_trans_rec(const irep_idt &, idst &) const;
6061
};
6162

63+
/// Class hierarchy graph node: simply contains a class identifier.
64+
class class_hierarchy_graph_nodet : public graph_nodet<empty_edget>
65+
{
66+
public:
67+
/// Class ID for this node
68+
irep_idt class_identifier;
69+
};
70+
71+
/// Class hierarchy, represented using grapht and therefore suitable for use
72+
/// with generic graph algorithms.
73+
class class_hierarchy_grapht : public grapht<class_hierarchy_graph_nodet>
74+
{
75+
public:
76+
/// Maps class identifiers onto node indices
77+
typedef std::unordered_map<irep_idt, node_indext, irep_id_hash>
78+
nodes_by_namet;
79+
80+
void populate(const symbol_tablet &);
81+
82+
/// Get map from class identifier to node index
83+
/// \return map from class identifier to node index
84+
const nodes_by_namet &get_nodes_by_class_identifier() const
85+
{
86+
return nodes_by_name;
87+
}
88+
89+
private:
90+
/// Maps class identifiers onto node indices
91+
nodes_by_namet nodes_by_name;
92+
};
93+
6294
#endif // CPROVER_GOTO_PROGRAMS_CLASS_HIERARCHY_H

unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ SRC += unit_tests.cpp \
1818
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
1919
goto-programs/goto_trace_output.cpp \
2020
goto-programs/class_hierarchy_output.cpp \
21+
goto-programs/class_hierarchy_graph.cpp \
2122
java_bytecode/java_bytecode_convert_class/convert_abstract_class.cpp \
2223
java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp \
2324
java_bytecode/java_object_factory/gen_nondet_string_init.cpp \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for class_hierarchy_grapht
4+
5+
Author: Diffblue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
#include <testing-utils/load_java_class.h>
11+
12+
#include <goto-programs/class_hierarchy.h>
13+
14+
void require_parent_child_relationship(
15+
const std::string &parent_raw,
16+
const std::string &child_raw,
17+
const class_hierarchy_grapht &hierarchy)
18+
{
19+
irep_idt parent = "java::" + parent_raw;
20+
irep_idt child = "java::" + child_raw;
21+
22+
const class_hierarchy_grapht::nodes_by_namet &nodes_map =
23+
hierarchy.get_nodes_by_class_identifier();
24+
REQUIRE(nodes_map.count(parent) != 0);
25+
REQUIRE(nodes_map.count(child) != 0);
26+
REQUIRE(hierarchy.has_edge(nodes_map.at(parent), nodes_map.at(child)));
27+
}
28+
29+
SCENARIO(
30+
"Output a simple class hierarchy"
31+
"[core][goto-programs][class_hierarchy_graph]")
32+
{
33+
symbol_tablet symbol_table =
34+
load_java_class("HierarchyTest", "goto-programs/");
35+
class_hierarchy_grapht hierarchy;
36+
hierarchy.populate(symbol_table);
37+
38+
require_parent_child_relationship(
39+
"HierarchyTest", "HierarchyTestChild1", hierarchy);
40+
require_parent_child_relationship(
41+
"HierarchyTest", "HierarchyTestChild2", hierarchy);
42+
require_parent_child_relationship(
43+
"HierarchyTestChild1", "HierarchyTestGrandchild", hierarchy);
44+
require_parent_child_relationship(
45+
"HierarchyTestInterface1", "HierarchyTestGrandchild", hierarchy);
46+
require_parent_child_relationship(
47+
"HierarchyTestInterface2", "HierarchyTestGrandchild", hierarchy);
48+
}

0 commit comments

Comments
 (0)