-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathdirty.cpp
119 lines (104 loc) · 3.16 KB
/
dirty.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
117
118
119
/*******************************************************************\
Module: Local variables whose address is taken
Author: Daniel Kroening
Date: March 2013
\*******************************************************************/
/// \file
/// Local variables whose address is taken
#include "dirty.h"
#include <util/pointer_expr.h>
#include <util/std_expr.h>
void dirtyt::build(const goto_functiont &goto_function)
{
for(const auto &i : goto_function.body.instructions)
{
if(i.is_other())
{
search_other(i);
}
else
{
i.apply([this](const exprt &e) { find_dirty(e); });
}
}
}
void dirtyt::search_other(const goto_programt::instructiont &instruction)
{
INVARIANT(instruction.is_other(), "instruction type must be OTHER");
if(instruction.get_other().id() == ID_code)
{
const codet &code = instruction.get_other();
const irep_idt &statement = code.get_statement();
if(
statement == ID_expression || statement == ID_array_set ||
statement == ID_array_equal || statement == ID_array_copy ||
statement == ID_array_replace || statement == ID_havoc_object ||
statement == ID_input || statement == ID_output)
{
for(const auto &op : code.operands())
find_dirty(op);
}
// other possible cases according to goto_programt::instructiont::output
// and goto_symext::symex_other:
// statement == ID_fence ||
// statement == ID_user_specified_predicate ||
// statement == ID_user_specified_parameter_predicates ||
// statement == ID_user_specified_return_predicates ||
// statement == ID_decl || statement == ID_nondet || statement == ID_asm)
}
}
void dirtyt::find_dirty(const exprt &expr)
{
if(expr.id() == ID_address_of)
{
const address_of_exprt &address_of_expr = to_address_of_expr(expr);
find_dirty_address_of(address_of_expr.object());
return;
}
for(const auto &op : expr.operands())
find_dirty(op);
}
void dirtyt::find_dirty_address_of(const exprt &expr)
{
if(expr.id() == ID_symbol)
{
const irep_idt &identifier = to_symbol_expr(expr).get_identifier();
dirty.insert(identifier);
}
else if(expr.id() == ID_member)
{
find_dirty_address_of(to_member_expr(expr).struct_op());
}
else if(expr.id() == ID_index)
{
find_dirty_address_of(to_index_expr(expr).array());
find_dirty(to_index_expr(expr).index());
}
else if(expr.id() == ID_dereference)
{
find_dirty(to_dereference_expr(expr).pointer());
}
else if(expr.id() == ID_if)
{
find_dirty_address_of(to_if_expr(expr).true_case());
find_dirty_address_of(to_if_expr(expr).false_case());
find_dirty(to_if_expr(expr).cond());
}
}
void dirtyt::output(std::ostream &out) const
{
die_if_uninitialized();
for(const auto &d : dirty)
out << d << '\n';
}
/// Analyse the given function with dirtyt if it hasn't been seen before
/// \param id: function id to analyse
/// \param function: function to analyse
void incremental_dirtyt::populate_dirty_for_function(
const irep_idt &id,
const goto_functionst::goto_functiont &function)
{
auto insert_result = dirty_processed_functions.insert(id);
if(insert_result.second)
dirty.add_function(function);
}