-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathsentinel_dll.cpp
82 lines (64 loc) · 1.78 KB
/
sentinel_dll.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
/*******************************************************************\
Module: Sentinel Doubly Linked Lists
Author: Daniel Kroening, [email protected]
\*******************************************************************/
/// \file
/// Axioms
#include "sentinel_dll.h"
#include <util/c_types.h>
#include <util/namespace.h>
#include <util/pointer_expr.h>
#include "state.h"
std::optional<exprt> sentinel_dll_member(
const exprt &state,
const exprt &node,
bool next, // vs. prev
const namespacet &ns)
{
if(node.type().id() != ID_pointer)
return {};
if(to_pointer_type(node.type()).base_type().id() != ID_struct_tag)
return {};
const auto &struct_type =
ns.follow_tag(to_struct_tag_type(to_pointer_type(node.type()).base_type()));
// the first pointer to a struct is 'next', the second 'prev'
const struct_typet::componentt *next_m = nullptr, *prev_m = nullptr;
for(auto &m : struct_type.components())
{
if(m.type() == node.type()) // we are strict on the type
{
if(next_m == nullptr)
next_m = &m;
else
prev_m = &m;
}
}
struct_typet::componentt component;
if(next)
{
if(next_m == nullptr)
return {};
else
component = *next_m;
}
else
{
if(prev_m == nullptr)
return {};
else
component = *prev_m;
}
auto field_address = field_address_exprt(
node, component.get_name(), pointer_type(component.type()));
return evaluate_exprt(state, field_address, component.type());
}
std::optional<exprt>
sentinel_dll_next(const exprt &state, const exprt &node, const namespacet &ns)
{
return sentinel_dll_member(state, node, true, ns);
}
std::optional<exprt>
sentinel_dll_prev(const exprt &state, const exprt &node, const namespacet &ns)
{
return sentinel_dll_member(state, node, false, ns);
}