Skip to content

Commit 7ab2670

Browse files
author
martin
committed
Refactor the methods that access "the abstract domain at a location".
This allows us to be a lot more flexible about the relationship between location and domain rather than assuming it is a 1-to-1 map.
1 parent 08bd1a8 commit 7ab2670

File tree

2 files changed

+26
-11
lines changed

2 files changed

+26
-11
lines changed

src/analyses/ai.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void ai_baset::output(
5050
out << "**** " << i_it->location_number << " "
5151
<< i_it->source_location << "\n";
5252

53-
find_state(i_it).output(out, *this, ns);
53+
abstract_state_before(i_it)->output(out, *this, ns);
5454
out << "\n";
5555
#if 1
5656
goto_program.output_instruction(ns, identifier, out, *i_it);
@@ -101,7 +101,8 @@ jsont ai_baset::output_json(
101101
json_numbert(std::to_string(i_it->location_number));
102102
location["sourceLocation"]=
103103
json_stringt(i_it->source_location.as_string());
104-
location["abstractState"]=find_state(i_it).output_json(*this, ns);
104+
location["abstractState"]=
105+
abstract_state_before(i_it)->output_json(*this, ns);
105106

106107
// Ideally we need output_instruction_json
107108
std::ostringstream out;
@@ -162,7 +163,7 @@ xmlt ai_baset::output_xml(
162163
"source_location",
163164
i_it->source_location.as_string());
164165

165-
location.new_element(find_state(i_it).output_xml(*this, ns));
166+
location.new_element(abstract_state_before(i_it)->output_xml(*this, ns));
166167

167168
// Ideally we need output_instruction_xml
168169
std::ostringstream out;

src/analyses/ai.h

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,22 @@ class ai_baset
8282
finalize();
8383
}
8484

85+
/// Accessing individual domains at particular domains
86+
/// (without needing to know what kind of domain or history is used)
87+
/// A pointer to a copy as the method should be const and
88+
/// there are some non-trivial cases including merging domains, etc.
89+
8590
/// Returns the abstract state before the given instruction
86-
virtual const ai_domain_baset & abstract_state_before(
87-
goto_programt::const_targett t) const = 0;
91+
/// PRECONDITION(l is dereferenceable)
92+
virtual std::unique_ptr<statet> abstract_state_before(locationt l) const = 0;
8893

8994
/// Returns the abstract state after the given instruction
90-
virtual const ai_domain_baset & abstract_state_after(
91-
goto_programt::const_targett t) const
95+
virtual std::unique_ptr<statet> abstract_state_after(locationt l) const
9296
{
93-
return abstract_state_before(std::next(t));
97+
/// PRECONDITION(l is dereferenceable && std::next(l) is dereferenceable)
98+
/// Check relies on a DATA_INVARIANT of goto_programs
99+
INVARIANT(!l->is_end_function(), "No state after the last instruction");
100+
return abstract_state_before(std::next(l));
94101
}
95102

96103
virtual void clear()
@@ -304,10 +311,17 @@ class ait:public ai_baset
304311
return it->second;
305312
}
306313

307-
const ai_domain_baset & abstract_state_before(
308-
goto_programt::const_targett t) const override
314+
std::unique_ptr<statet> abstract_state_before(locationt t) const override
309315
{
310-
return (*this)[t];
316+
typename state_mapt::const_iterator it=state_map.find(t);
317+
if(it==state_map.end())
318+
{
319+
std::unique_ptr<statet> d = util_make_unique<domainT>();
320+
CHECK_RETURN(d->is_bottom());
321+
return d;
322+
}
323+
324+
return util_make_unique<domainT>(it->second);
311325
}
312326

313327
void clear() override

0 commit comments

Comments
 (0)