Skip to content

Commit cd4fc7b

Browse files
Merge pull request #471 from smowton/factor_class_identifier_master
Factor class identifier extraction out of remove virtuals
2 parents f171d24 + 9e73f42 commit cd4fc7b

File tree

4 files changed

+123
-64
lines changed

4 files changed

+123
-64
lines changed

src/goto-programs/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ SRC = goto_convert.cpp goto_convert_function_call.cpp \
1717
goto_trace.cpp xml_goto_trace.cpp vcd_goto_trace.cpp \
1818
graphml_witness.cpp remove_virtual_functions.cpp \
1919
class_hierarchy.cpp show_goto_functions.cpp get_goto_model.cpp \
20-
slice_global_inits.cpp goto_inline_class.cpp
20+
slice_global_inits.cpp goto_inline_class.cpp class_identifier.cpp
2121

2222
INCLUDES= -I ..
2323

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*******************************************************************\
2+
3+
Module: Extract class identifier
4+
5+
Author: Chris Smowton, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "class_identifier.h"
10+
11+
#include <util/std_expr.h>
12+
#include <util/namespace.h>
13+
14+
/*******************************************************************\
15+
16+
Function: build_class_identifier
17+
18+
Inputs: Struct expression
19+
20+
Outputs: Member expression giving the clsid field of the input,
21+
or its parent, grandparent, etc.
22+
23+
Purpose:
24+
25+
\*******************************************************************/
26+
27+
static exprt build_class_identifier(
28+
const exprt &src,
29+
const namespacet &ns)
30+
{
31+
// the class identifier is in the root class
32+
exprt e=src;
33+
34+
while(1)
35+
{
36+
const typet &type=ns.follow(e.type());
37+
const struct_typet &struct_type=to_struct_type(type);
38+
const struct_typet::componentst &components=struct_type.components();
39+
assert(!components.empty());
40+
41+
const auto &first_member_name=components.front().get_name();
42+
member_exprt member_expr(
43+
e,
44+
first_member_name,
45+
components.front().type());
46+
47+
if(first_member_name=="@class_identifier")
48+
{
49+
// found it
50+
return member_expr;
51+
}
52+
else
53+
{
54+
e.swap(member_expr);
55+
}
56+
}
57+
}
58+
59+
/*******************************************************************\
60+
61+
Function: get_class_identifier_field
62+
63+
Inputs: Pointer expression of any pointer type, including void*,
64+
and a recommended access type if the pointer is void-typed.
65+
66+
Outputs: Member expression to access a class identifier, as above.
67+
68+
Purpose:
69+
70+
\*******************************************************************/
71+
72+
exprt get_class_identifier_field(
73+
const exprt &this_expr_in,
74+
const symbol_typet &suggested_type,
75+
const namespacet &ns)
76+
{
77+
// Get a pointer from which we can extract a clsid.
78+
// If it's already a pointer to an object of some sort, just use it;
79+
// if it's void* then use the suggested type.
80+
81+
exprt this_expr=this_expr_in;
82+
assert(this_expr.type().id()==ID_pointer &&
83+
"Non-pointer this-arg in remove-virtuals?");
84+
const auto &points_to=this_expr.type().subtype();
85+
if(points_to==empty_typet())
86+
this_expr=typecast_exprt(this_expr, pointer_typet(suggested_type));
87+
exprt deref=dereference_exprt(this_expr, this_expr.type().subtype());
88+
return build_class_identifier(deref, ns);
89+
}

src/goto-programs/class_identifier.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*******************************************************************\
2+
3+
Module: Extract class identifier
4+
5+
Author: Chris Smowton, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H
10+
#define CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H
11+
12+
class exprt;
13+
class namespacet;
14+
class symbol_typet;
15+
16+
exprt get_class_identifier_field(
17+
const exprt &this_expr,
18+
const symbol_typet &suggested_type,
19+
const namespacet &ns);
20+
21+
#endif

src/goto-programs/remove_virtual_functions.cpp

+12-63
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
#include <util/type_eq.h>
1111

1212
#include "class_hierarchy.h"
13+
#include "class_identifier.h"
1314
#include "remove_virtual_functions.h"
1415

1516
/*******************************************************************\
@@ -61,8 +62,6 @@ class remove_virtual_functionst
6162
exprt get_method(
6263
const irep_idt &class_id,
6364
const irep_idt &component_name) const;
64-
65-
exprt build_class_identifier(const exprt &);
6665
};
6766

6867
/*******************************************************************\
@@ -88,48 +87,6 @@ remove_virtual_functionst::remove_virtual_functionst(
8887

8988
/*******************************************************************\
9089
91-
Function: remove_virtual_functionst::build_class_identifier
92-
93-
Inputs:
94-
95-
Outputs:
96-
97-
Purpose:
98-
99-
\*******************************************************************/
100-
101-
exprt remove_virtual_functionst::build_class_identifier(
102-
const exprt &src)
103-
{
104-
// the class identifier is in the root class
105-
exprt e=src;
106-
107-
while(1)
108-
{
109-
const typet &type=ns.follow(e.type());
110-
assert(type.id()==ID_struct);
111-
112-
const struct_typet &struct_type=to_struct_type(type);
113-
const struct_typet::componentst &components=struct_type.components();
114-
assert(!components.empty());
115-
116-
member_exprt member_expr(
117-
e, components.front().get_name(), components.front().type());
118-
119-
if(components.front().get_name()=="@class_identifier")
120-
{
121-
// found it
122-
return member_expr;
123-
}
124-
else
125-
{
126-
e=member_expr;
127-
}
128-
}
129-
}
130-
131-
/*******************************************************************\
132-
13390
Function: remove_virtual_functionst::remove_virtual_function
13491
13592
Inputs:
@@ -181,22 +138,12 @@ void remove_virtual_functionst::remove_virtual_function(
181138
goto_programt new_code_calls;
182139
goto_programt new_code_gotos;
183140

184-
// Get a pointer from which we can extract a clsid.
185-
// If it's already a pointer to an object of some sort, just use it;
186-
// if it's void* then use the parent of all possible candidates,
187-
// which by the nature of get_functions happens to be the last candidate.
188-
189141
exprt this_expr=code.arguments()[0];
190-
assert(this_expr.type().id()==ID_pointer &&
191-
"Non-pointer this-arg in remove-virtuals?");
192-
const auto &points_to=this_expr.type().subtype();
193-
if(points_to==empty_typet())
194-
{
195-
symbol_typet symbol_type(functions.back().class_id);
196-
this_expr=typecast_exprt(this_expr, pointer_typet(symbol_type));
197-
}
198-
exprt deref=dereference_exprt(this_expr, this_expr.type().subtype());
199-
exprt c_id2=build_class_identifier(deref);
142+
// If necessary, cast to the last candidate function to
143+
// get the object's clsid. By the structure of get_functions,
144+
// this is the parent of all other classes under consideration.
145+
symbol_typet suggested_type(functions.back().class_id);
146+
exprt c_id2=get_class_identifier_field(this_expr, suggested_type, ns);
200147

201148
goto_programt::targett last_function;
202149
for(const auto &fun : functions)
@@ -249,8 +196,10 @@ void remove_virtual_functionst::remove_virtual_function(
249196
const irep_idt comment=it->source_location.get_comment();
250197
it->source_location=target->source_location;
251198
it->function=target->function;
252-
if(!property_class.empty()) it->source_location.set_property_class(property_class);
253-
if(!comment.empty()) it->source_location.set_comment(comment);
199+
if(!property_class.empty())
200+
it->source_location.set_property_class(property_class);
201+
if(!comment.empty())
202+
it->source_location.set_comment(comment);
254203
}
255204

256205
goto_programt::targett next_target=target;
@@ -355,7 +304,8 @@ void remove_virtual_functionst::get_functions(
355304
const class_hierarchyt::idst &parents=
356305
class_hierarchy.class_map[c].parents;
357306

358-
if(parents.empty()) break;
307+
if(parents.empty())
308+
break;
359309
c=parents.front();
360310
}
361311

@@ -433,7 +383,6 @@ bool remove_virtual_functionst::remove_virtual_functions(
433383

434384
if(did_something)
435385
{
436-
//remove_skip(goto_program);
437386
goto_program.update();
438387
}
439388

0 commit comments

Comments
 (0)