-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathcpp_destructor.cpp
116 lines (85 loc) · 2.97 KB
/
cpp_destructor.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
110
111
112
113
114
115
116
/*******************************************************************\
Module: C++ Language Type Checking
Author: Daniel Kroening, [email protected]
\*******************************************************************/
/// \file
/// C++ Language Type Checking
#include "cpp_typecheck.h"
#include <util/arith_tools.h>
#include <util/c_types.h>
/// \return typechecked code
std::optional<codet> cpp_typecheckt::cpp_destructor(
const source_locationt &source_location,
const exprt &object)
{
elaborate_class_template(object.type());
CHECK_RETURN(!is_reference(object.type()));
// PODs don't need a destructor
if(cpp_is_pod(object.type()))
return {};
if(object.type().id() == ID_array)
{
const exprt &size_expr = to_array_type(object.type()).size();
if(size_expr.id() == ID_infinity)
return {}; // don't initialize
exprt tmp_size=size_expr;
make_constant_index(tmp_size);
mp_integer s;
if(to_integer(to_constant_expr(tmp_size), s))
{
error().source_location=source_location;
error() << "array size '" << to_string(size_expr) << "' is not a constant"
<< eom;
throw 0;
}
code_blockt new_code;
new_code.add_source_location()=source_location;
// for each element of the array, call the destructor
for(mp_integer i=0; i < s; ++i)
{
exprt constant = from_integer(i, c_index_type());
constant.add_source_location()=source_location;
index_exprt index(object, constant);
index.add_source_location()=source_location;
auto i_code = cpp_destructor(source_location, index);
if(i_code.has_value())
new_code.add_to_operands(std::move(i_code.value()));
}
return std::move(new_code);
}
else
{
const struct_typet &struct_type =
follow_tag(to_struct_tag_type(object.type()));
// enter struct scope
cpp_save_scopet save_scope(cpp_scopes);
cpp_scopes.set_scope(struct_type.get(ID_name));
// find name of destructor
const struct_typet::componentst &components=
struct_type.components();
irep_idt dtor_name;
for(const auto &c : components)
{
const typet &type = c.type();
if(
!c.get_bool(ID_from_base) && type.id() == ID_code &&
to_code_type(type).return_type().id() == ID_destructor)
{
dtor_name = c.get_base_name();
break;
}
}
INVARIANT(!dtor_name.empty(), "non-PODs should have a destructor");
cpp_namet cpp_name(dtor_name, source_location);
exprt member(ID_member);
member.add(ID_component_cpp_name) = cpp_name;
member.copy_to_operands(object);
side_effect_expr_function_callt function_call(
std::move(member), {}, uninitialized_typet{}, source_location);
typecheck_side_effect_function_call(function_call);
already_typechecked_exprt::make_already_typechecked(function_call);
code_expressiont new_code(function_call);
new_code.add_source_location() = source_location;
return std::move(new_code);
}
}