-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathclass_identifier.cpp
109 lines (94 loc) · 3.43 KB
/
class_identifier.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*******************************************************************\
Module: Extract class identifier
Author: Chris Smowton, [email protected]
\*******************************************************************/
/// \file
/// Extract class identifier
#include "class_identifier.h"
#include <util/c_types.h>
#include <util/namespace.h>
#include <util/pointer_expr.h>
#include <util/std_expr.h>
/// \par parameters: Struct expression
/// \return Member expression giving the clsid field of the input, or its
/// parent, grandparent, etc.
static exprt build_class_identifier(
const exprt &src,
const namespacet &ns)
{
// the class identifier is in the root class
exprt e=src;
while(1)
{
const struct_typet &struct_type =
ns.follow_tag(to_struct_tag_type(e.type()));
const struct_typet::componentst &components=struct_type.components();
INVARIANT(!components.empty(), "class structs cannot be empty");
const auto &first_member_name=components.front().get_name();
member_exprt member_expr(
e,
first_member_name,
components.front().type());
if(first_member_name == JAVA_CLASS_IDENTIFIER_FIELD_NAME)
{
// found it
return std::move(member_expr);
}
else
{
e.swap(member_expr);
}
}
}
/// \par parameters: Pointer expression of any pointer type, including void*,
/// and a recommended access type if the pointer is void-typed.
/// \return Member expression to access a class identifier, as above.
exprt get_class_identifier_field(
const exprt &this_expr_in,
const struct_tag_typet &suggested_type,
const namespacet &ns)
{
// Get a pointer from which we can extract a clsid.
// If it's already a pointer to an object of some sort, just use it;
// if it's void* then use the suggested type.
PRECONDITION(this_expr_in.type().id() == ID_pointer);
exprt this_expr=this_expr_in;
const auto &points_to = to_pointer_type(this_expr.type()).base_type();
if(points_to==empty_typet())
this_expr=typecast_exprt(this_expr, pointer_type(suggested_type));
const dereference_exprt deref{this_expr};
return build_class_identifier(deref, ns);
}
/// If expr has its components filled in then sets the `@class_identifier`
/// member of the struct
/// \remarks Follows through base class members until it gets to the object
/// type that contains the `@class_identifier` member
/// \param expr: An expression that represents a struct
/// \param ns: The namespace used to resolve symbol references in the type of
/// the struct
/// \param class_type: A symbol whose identifier is the name of the class
void set_class_identifier(
struct_exprt &expr,
const namespacet &ns,
const struct_tag_typet &class_type)
{
const struct_typet &struct_type =
ns.follow_tag(to_struct_tag_type(expr.type()));
const struct_typet::componentst &components=struct_type.components();
if(components.empty())
// Presumably this means the type has not yet been determined
return;
PRECONDITION(!expr.operands().empty());
if(components.front().get_name() == JAVA_CLASS_IDENTIFIER_FIELD_NAME)
{
INVARIANT(expr.op0().is_constant(), "@class_identifier must be a constant");
expr.op0()=constant_exprt(class_type.get_identifier(), string_typet());
}
else
{
// The first member must be the base class
INVARIANT(
expr.op0().id()==ID_struct, "Non @class_identifier must be a structure");
set_class_identifier(to_struct_expr(expr.op0()), ns, class_type);
}
}