Skip to content

Commit 3e51909

Browse files
committed
Factor class identifier extraction out of remove virtuals
This will be useful for other passes that inspect an object's dynamic clsid, such as the forthcoming lower-instanceof pass.
1 parent f488acd commit 3e51909

File tree

4 files changed

+116
-60
lines changed

4 files changed

+116
-60
lines changed

src/goto-programs/Makefile

Lines changed: 1 addition & 1 deletion
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

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*******************************************************************\
2+
3+
Module: Extract class identifier
4+
5+
Author: Chris Smowton, chris.smowton@diffblue.com
6+
7+
\*******************************************************************/
8+
9+
#include "class_identifier.h"
10+
11+
#include <util/std_expr.h>
12+
13+
/*******************************************************************\
14+
15+
Function: build_class_identifier
16+
17+
Inputs: Struct expression
18+
19+
Outputs: Member expression giving the clsid field of the input,
20+
or its parent, grandparent, etc.
21+
22+
Purpose:
23+
24+
\*******************************************************************/
25+
26+
static exprt build_class_identifier(
27+
const exprt &src,
28+
const namespacet &ns)
29+
{
30+
// the class identifier is in the root class
31+
exprt e=src;
32+
33+
while(1)
34+
{
35+
const typet &type=ns.follow(e.type());
36+
assert(type.id()==ID_struct);
37+
38+
const struct_typet &struct_type=to_struct_type(type);
39+
const struct_typet::componentst &components=struct_type.components();
40+
assert(!components.empty());
41+
42+
member_exprt member_expr(
43+
e,
44+
components.front().get_name(),
45+
components.front().type());
46+
47+
if(components.front().get_name()=="@class_identifier")
48+
{
49+
// found it
50+
return member_expr;
51+
}
52+
else
53+
{
54+
e=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+
exprt this_expr,
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+
assert(this_expr.type().id()==ID_pointer &&
82+
"Non-pointer this-arg in remove-virtuals?");
83+
const auto& points_to=this_expr.type().subtype();
84+
if(points_to==empty_typet())
85+
this_expr=typecast_exprt(this_expr, pointer_typet(suggested_type));
86+
exprt deref=dereference_exprt(this_expr, this_expr.type().subtype());
87+
return build_class_identifier(deref, ns);
88+
}

src/goto-programs/class_identifier.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*******************************************************************\
2+
3+
Module: Extract class identifier
4+
5+
Author: Chris Smowton, chris.smowton@diffblue.com
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H
10+
#define CPROVER_GOTO_PROGRAMS_CLASS_IDENTIFIER_H
11+
12+
#include <util/expr.h>
13+
#include <util/std_types.h>
14+
#include <util/namespace.h>
15+
16+
exprt get_class_identifier_field(
17+
exprt this_expr,
18+
const symbol_typet &suggested_type,
19+
const namespacet &ns);
20+
21+
#endif

src/goto-programs/remove_virtual_functions.cpp

Lines changed: 6 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, kroening@kroening.com
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 get the object's clsid.
143+
// By the structure of get_functions, this is the parent of all other classes
144+
// 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)

0 commit comments

Comments
 (0)