@@ -13,43 +13,13 @@ Date: April 2016
13
13
14
14
#include " class_hierarchy.h"
15
15
16
+ #include < iterator>
16
17
#include < ostream>
17
18
18
19
#include < util/json_stream.h>
19
20
#include < util/std_types.h>
20
21
#include < util/symbol_table.h>
21
22
22
- // / Looks for all the struct types in the symbol table and construct a map from
23
- // / class names to a data structure that contains lists of parent and child
24
- // / classes for each struct type (ie class).
25
- // / \param symbol_table: The symbol table to analyze
26
- void class_hierarchyt::operator ()(const symbol_tablet &symbol_table)
27
- {
28
- for (const auto &symbol_pair : symbol_table.symbols )
29
- {
30
- if (symbol_pair.second .is_type && symbol_pair.second .type .id () == ID_struct)
31
- {
32
- const struct_typet &struct_type = to_struct_type (symbol_pair.second .type );
33
-
34
- class_map[symbol_pair.first ].is_abstract =
35
- struct_type.get_bool (ID_abstract);
36
-
37
- const irept::subt &bases=
38
- struct_type.find (ID_bases).get_sub ();
39
-
40
- for (const auto &base : bases)
41
- {
42
- irep_idt parent=base.find (ID_type).get (ID_identifier);
43
- if (parent.empty ())
44
- continue ;
45
-
46
- class_map[parent].children .push_back (symbol_pair.first );
47
- class_map[symbol_pair.first ].parents .push_back (parent);
48
- }
49
- }
50
- }
51
- }
52
-
53
23
// / Populate the class hierarchy graph, such that there is a node for every
54
24
// / struct type in the symbol table and an edge representing each superclass
55
25
// / <-> subclass relationship, pointing from parent to child.
@@ -88,6 +58,70 @@ void class_hierarchy_grapht::populate(const symbol_tablet &symbol_table)
88
58
}
89
59
}
90
60
61
+ // / Helper function that converts a vector of node_indext to a vector of ids
62
+ // / that are stored in the corresponding nodes in the graph.
63
+ class_hierarchy_grapht::idst class_hierarchy_grapht::ids_from_indices (
64
+ const std::vector<node_indext> &node_indices) const
65
+ {
66
+ idst result;
67
+ std::transform (
68
+ node_indices.begin (),
69
+ node_indices.end (),
70
+ back_inserter (result),
71
+ [&](const node_indext &node_index) {
72
+ return (*this )[node_index].class_identifier ;
73
+ });
74
+ return result;
75
+ }
76
+
77
+ // / Get all the classes that directly (i.e. in one step) inherit from class c.
78
+ // / \param c: The class to consider
79
+ // / \return A list containing ids of all direct children of c.
80
+ class_hierarchy_grapht::idst
81
+ class_hierarchy_grapht::get_direct_children (const irep_idt &c) const
82
+ {
83
+ const node_indext &node_index = nodes_by_name.at (c);
84
+ const auto &child_indices = get_successors (node_index);
85
+ return ids_from_indices (child_indices);
86
+ }
87
+
88
+ // / Helper function for `get_children_trans` and `get_parents_trans`
89
+ class_hierarchy_grapht::idst class_hierarchy_grapht::get_other_reachable_ids (
90
+ const irep_idt &c,
91
+ bool forwards) const
92
+ {
93
+ idst direct_child_ids;
94
+ const node_indext &node_index = nodes_by_name.at (c);
95
+ const auto &reachable_indices = get_reachable (node_index, forwards);
96
+ auto reachable_ids = ids_from_indices (reachable_indices);
97
+ // Remove c itself from the list
98
+ // TODO Adding it first and then removing it is not ideal. It would be
99
+ // better to define a function grapht::get_other_reachable and directly use
100
+ // that here.
101
+ reachable_ids.erase (
102
+ std::remove (reachable_ids.begin (), reachable_ids.end (), c),
103
+ reachable_ids.end ());
104
+ return reachable_ids;
105
+ }
106
+
107
+ // / Get all the classes that inherit (directly or indirectly) from class c.
108
+ // / \param c: The class to consider
109
+ // / \return A list containing ids of all classes that eventually inherit from c.
110
+ class_hierarchy_grapht::idst
111
+ class_hierarchy_grapht::get_children_trans (const irep_idt &c) const
112
+ {
113
+ return get_other_reachable_ids (c, true );
114
+ }
115
+
116
+ // / Get all the classes that class c inherits from (directly or indirectly).
117
+ // / \param c: The class to consider
118
+ // / \return A list of class ids that c eventually inherits from.
119
+ class_hierarchy_grapht::idst
120
+ class_hierarchy_grapht::get_parents_trans (const irep_idt &c) const
121
+ {
122
+ return get_other_reachable_ids (c, false );
123
+ }
124
+
91
125
void class_hierarchyt::get_children_trans_rec (
92
126
const irep_idt &c,
93
127
idst &dest) const
@@ -105,7 +139,37 @@ void class_hierarchyt::get_children_trans_rec(
105
139
get_children_trans_rec (child, dest);
106
140
}
107
141
108
- // / Get all the classes that inherit (directly or indirectly) from class c. The
142
+ // / Looks for all the struct types in the symbol table and construct a map from
143
+ // / class names to a data structure that contains lists of parent and child
144
+ // / classes for each struct type (ie class).
145
+ // / \param symbol_table: The symbol table to analyze
146
+ void class_hierarchyt::operator ()(const symbol_tablet &symbol_table)
147
+ {
148
+ for (const auto &symbol_pair : symbol_table.symbols )
149
+ {
150
+ if (symbol_pair.second .is_type && symbol_pair.second .type .id () == ID_struct)
151
+ {
152
+ const struct_typet &struct_type = to_struct_type (symbol_pair.second .type );
153
+
154
+ class_map[symbol_pair.first ].is_abstract =
155
+ struct_type.get_bool (ID_abstract);
156
+
157
+ const irept::subt &bases = struct_type.find (ID_bases).get_sub ();
158
+
159
+ for (const auto &base : bases)
160
+ {
161
+ irep_idt parent = base.find (ID_type).get (ID_identifier);
162
+ if (parent.empty ())
163
+ continue ;
164
+
165
+ class_map[parent].children .push_back (symbol_pair.first );
166
+ class_map[symbol_pair.first ].parents .push_back (parent);
167
+ }
168
+ }
169
+ }
170
+ }
171
+
172
+ // / Get all the classes that class c inherits from (directly or indirectly). The
109
173
// / first element(s) will be the immediate parents of c, though after this
110
174
// / the order is all the parents of the first immediate parent
111
175
// / \param c: The class to consider
0 commit comments