Skip to content

Commit 6e67bf5

Browse files
committed
Use unique_ptr for domains and strategy solvers
Instead of using raw pointers and managing memory manually, start using unique_ptr. If an object contains a unique_ptr to another object as a member, it is the owner. In particular: - template generator owns the abstract domain - ssa analyzer owns the abstract value - ssa analyzer owns the strategy solver (as a local variable in operator()) - product domain owns the inner domains, likewise for the product value and for the product strategy solver - sympath domain owns the inner domain, likewise for the sympath solver - sympath value owns all the inner values for individual symbolic paths, it also owns the inner value template Generic abstract value has an abstract method "clone" that returns a covariant type. Since this cannot be implemented using unique_ptr, it returns a raw pointer. The caller is therefore responsible for taking ownership of the cloned object.
1 parent e862e8f commit 6e67bf5

11 files changed

+139
-139
lines changed

src/domains/domain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ class domaint
9797
/// Each abstract value needs to implement clone with covariant return type.
9898
/// This is needed to properly clone abstract value when only a pointer to
9999
/// valuet is available.
100+
/// Since the method returns a raw pointer, the caller is responsible for
101+
/// taking ownership of the created object.
100102
virtual valuet *clone()=0;
101103

102104
basic_valuet basic_value;

src/domains/product_domain.h

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Author: Viktor Malik
1717

1818
#include "domain.h"
1919
#include "strategy_solver_base.h"
20+
#include <memory>
21+
22+
typedef std::vector<std::unique_ptr<domaint>> domain_vect;
23+
typedef std::vector<std::unique_ptr<domaint::valuet>> value_vect;
2024

2125
class product_domaint:public domaint
2226
{
@@ -25,38 +29,23 @@ class product_domaint:public domaint
2529
unsigned int domainNumber,
2630
replace_mapt &renamingMap,
2731
const namespacet &ns,
28-
const std::vector<domaint *> &domains):
29-
domaint(domainNumber, renamingMap, ns), domains(domains) {}
30-
31-
// The domain owns the inner domains, therefore it must delete them properly
32-
~product_domaint() override
33-
{
34-
for(auto &domain : domains)
35-
delete domain;
36-
}
32+
domain_vect domains):
33+
domaint(domainNumber, renamingMap, ns), domains(std::move(domains)) {}
3734

3835
/// Abstract value is a vector of abstract values of inner domains.
3936
/// The order has to match the order of domains.
40-
struct valuet:domaint::valuet, std::vector<domaint::valuet *>
37+
struct valuet:domaint::valuet, value_vect
4138
{
4239
valuet()=default;
43-
explicit valuet(const std::vector<domaint::valuet *> &values):
44-
vector(values) {}
40+
explicit valuet(value_vect values):vector(std::move(values)) {}
4541

4642
valuet *clone() override
4743
{
4844
auto new_value=new valuet();
4945
for(const auto &val : *this)
50-
new_value->push_back(val->clone());
46+
new_value->emplace_back(val->clone());
5147
return new_value;
5248
}
53-
54-
// The value owns the inner values and therefore has to delete them
55-
~valuet() override
56-
{
57-
for(auto &val : *this)
58-
delete val;
59-
};
6049
};
6150

6251
// Most of the domain methods are implemented in such way that the
@@ -80,8 +69,17 @@ class product_domaint:public domaint
8069
void undo_sympath_restriction() override;
8170
void remove_all_sympath_restrictions() override;
8271

72+
/// Get a vector of raw pointers to the inner domains
73+
std::vector<domaint *> get_domains()
74+
{
75+
std::vector<domaint *> result;
76+
for(auto &d : domains)
77+
result.push_back(d.get());
78+
return result;
79+
}
80+
8381
// Product domain contains a vector of domains
84-
std::vector<domaint *> domains;
82+
domain_vect domains;
8583

8684
// Value is a vector of values in corresponding domains
8785
valuet value;

src/domains/ssa_analyzer.cpp

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,23 @@ void ssa_analyzert::operator()(
7878
domain=template_generator.domain();
7979

8080
// get strategy solver from options
81-
strategy_solver_baset *s_solver;
81+
std::unique_ptr<strategy_solver_baset> s_solver;
8282
if(template_generator.options.get_bool_option("compute-ranking-functions"))
8383
{
8484
if(template_generator.options.get_bool_option(
8585
"monolithic-ranking-function"))
8686
{
87-
s_solver=new SIMPLE_SOLVER(domain, linrank_domaint);
88-
result=new linrank_domaint::templ_valuet();
87+
s_solver=std::unique_ptr<strategy_solver_baset>(
88+
new SIMPLE_SOLVER(domain, linrank_domaint));
89+
result=std::unique_ptr<domaint::valuet>(
90+
new linrank_domaint::templ_valuet());
8991
}
9092
else
9193
{
92-
s_solver=new SIMPLE_SOLVER(domain, lexlinrank_domaint);
93-
result=new lexlinrank_domaint::templ_valuet();
94+
s_solver=std::unique_ptr<strategy_solver_baset>(
95+
new SIMPLE_SOLVER(domain, lexlinrank_domaint));
96+
result=std::unique_ptr<domaint::valuet>(
97+
new lexlinrank_domaint::templ_valuet());
9498
}
9599
}
96100
else
@@ -99,37 +103,38 @@ void ssa_analyzert::operator()(
99103
// Check if symbolic paths domain is used. If so, invariant_domain points to
100104
// the inner domain of the symbolic paths domain.
101105
if(template_generator.options.get_bool_option("sympath"))
102-
invariant_domain=dynamic_cast<sympath_domaint *>(domain)->inner_domain;
106+
invariant_domain=
107+
dynamic_cast<sympath_domaint *>(domain)->inner_domain.get();
103108
else
104109
invariant_domain=domain;
105110

106-
// simple_domains contains a vector of simple domains used.
111+
// simple_domains contains a vector of pointers to simple domains used.
107112
// This is either invariant_domain (if a single simple domain is used) or
108113
// the vector of domains retrieved from the product domain.
109114
std::vector<domaint *> simple_domains;
110115
unsigned next_domain=0;
111116
auto *product_domain=dynamic_cast<product_domaint *>(invariant_domain);
112117
if(product_domain)
113-
simple_domains=product_domain->domains;
118+
simple_domains=product_domain->get_domains();
114119
else
115120
simple_domains.push_back(invariant_domain);
116121

117122
// Create list of solvers and values.
118123
// Important: these must follow the order of domains created in the
119124
// template generator.
120-
std::vector<strategy_solver_baset *> solvers;
121-
std::vector<domaint::valuet *> values;
125+
solver_vect solvers;
126+
value_vect values;
122127
if(template_generator.options.get_bool_option("equalities"))
123128
{
124-
solvers.push_back(
129+
solvers.emplace_back(
125130
new SIMPLE_SOLVER(simple_domains[next_domain++], equality_domaint));
126-
values.push_back(new equality_domaint::equ_valuet());
131+
values.emplace_back(new equality_domaint::equ_valuet());
127132
}
128133
if(template_generator.options.get_bool_option("heap"))
129134
{
130-
solvers.push_back(
135+
solvers.emplace_back(
131136
new SIMPLE_SOLVER(simple_domains[next_domain++], heap_domaint));
132-
values.push_back(new heap_domaint::heap_valuet());
137+
values.emplace_back(new heap_domaint::heap_valuet());
133138
}
134139
if(template_generator.options.get_bool_option("intervals") ||
135140
template_generator.options.get_bool_option("zones") ||
@@ -138,42 +143,49 @@ void ssa_analyzert::operator()(
138143
{
139144
if(template_generator.options.get_bool_option("enum-solver"))
140145
{
141-
solvers.push_back(
146+
solvers.emplace_back(
142147
new SIMPLE_SOLVER(simple_domains[next_domain++], tpolyhedra_domaint));
143-
values.push_back(new tpolyhedra_domaint::templ_valuet());
148+
values.emplace_back(new tpolyhedra_domaint::templ_valuet());
144149
}
145150
else if(template_generator.options.get_bool_option("predabs-solver"))
146151
{
147-
solvers.push_back(
152+
solvers.emplace_back(
148153
new SIMPLE_SOLVER(simple_domains[next_domain++], predabs_domaint));
149-
values.push_back(new predabs_domaint::templ_valuet());
154+
values.emplace_back(new predabs_domaint::templ_valuet());
150155
}
151156
else if(template_generator.options.get_bool_option("binsearch-solver"))
152157
{
153-
solvers.push_back(new BINSEARCH_SOLVER);
154-
values.push_back(new tpolyhedra_domaint::templ_valuet());
158+
solvers.emplace_back(new BINSEARCH_SOLVER);
159+
values.emplace_back(new tpolyhedra_domaint::templ_valuet());
155160
}
156161
else
157162
assert(false);
158163
}
159164

160165
if(solvers.size()==1)
161166
{
162-
s_solver=solvers[0];
163-
result=values[0];
167+
s_solver=std::move(solvers[0]);
168+
result=std::move(values[0]);
164169
}
165170
else
166171
{
167-
s_solver=new strategy_solver_productt(
168-
*product_domain, solver, SSA.ns, solvers);
169-
result=new product_domaint::valuet(values);
172+
s_solver=std::unique_ptr<strategy_solver_baset>(
173+
new strategy_solver_productt(
174+
*product_domain, solver, SSA.ns, std::move(solvers)));
175+
result=std::unique_ptr<domaint::valuet>(
176+
new product_domaint::valuet(std::move(values)));
170177
}
171178

172179
if(template_generator.options.get_bool_option("sympath"))
173180
{
174-
s_solver=new strategy_solver_sympatht(
175-
*dynamic_cast<sympath_domaint *>(domain), solver, SSA, s_solver);
176-
result=new sympath_domaint::sympath_valuet(result);
181+
s_solver=std::unique_ptr<strategy_solver_baset>(
182+
new strategy_solver_sympatht(
183+
*dynamic_cast<sympath_domaint *>(domain),
184+
solver,
185+
SSA,
186+
std::move(s_solver)));
187+
result=std::unique_ptr<domaint::valuet>(
188+
new sympath_domaint::sympath_valuet(std::move(result)));
177189
}
178190
}
179191

@@ -191,8 +203,6 @@ void ssa_analyzert::operator()(
191203
solver_instances+=s_solver->get_number_of_solver_instances();
192204
solver_calls+=s_solver->get_number_of_solver_calls();
193205
solver_instances+=s_solver->get_number_of_solver_instances();
194-
195-
delete s_solver;
196206
}
197207

198208
void ssa_analyzert::get_result(exprt &_result, const var_sett &vars)

src/domains/ssa_analyzer.h

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,6 @@ class ssa_analyzert:public messaget
2626
typedef strategy_solver_baset::constraintst constraintst;
2727
typedef strategy_solver_baset::var_listt var_listt;
2828

29-
ssa_analyzert():
30-
result(NULL),
31-
solver_instances(0),
32-
solver_calls(0)
33-
{
34-
}
35-
36-
~ssa_analyzert()
37-
{
38-
if(result!=NULL)
39-
delete result;
40-
}
41-
4229
void operator()(
4330
incremental_solvert &solver,
4431
local_SSAt &SSA,
@@ -51,8 +38,8 @@ class ssa_analyzert:public messaget
5138
inline unsigned get_number_of_solver_calls() { return solver_calls; }
5239

5340
protected:
54-
domaint *domain; // template generator is responsable for the domain object
55-
domaint::valuet *result;
41+
domaint *domain; // template generator is responsible for the domain object
42+
std::unique_ptr<domaint::valuet> result;
5643

5744
// statistics
5845
unsigned solver_instances;

src/domains/strategy_solver_product.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ Author: Viktor Malik
1717

1818
#include "strategy_solver_base.h"
1919
#include "product_domain.h"
20+
#include <memory>
21+
22+
typedef std::vector<std::unique_ptr<strategy_solver_baset>> solver_vect;
2023

2124
class strategy_solver_productt:public strategy_solver_baset
2225
{
@@ -25,8 +28,9 @@ class strategy_solver_productt:public strategy_solver_baset
2528
product_domaint &domain,
2629
incremental_solvert &solver,
2730
const namespacet &ns,
28-
const std::vector<strategy_solver_baset *> &solvers):
29-
strategy_solver_baset(solver, ns), domain(domain), solvers(solvers) {}
31+
solver_vect solvers):
32+
strategy_solver_baset(solver, ns), domain(domain),
33+
solvers(std::move(solvers)) {}
3034

3135
bool iterate(invariantt &inv) override;
3236

@@ -37,7 +41,7 @@ class strategy_solver_productt:public strategy_solver_baset
3741
protected:
3842
product_domaint &domain;
3943
// The solver contains a list of inner solvers
40-
std::vector<strategy_solver_baset *> solvers;
44+
solver_vect solvers;
4145
};
4246

4347
#endif // CPROVER_2LS_DOMAINS_STRATEGY_SOLVER_PRODUCT_H

src/domains/strategy_solver_sympath.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ bool strategy_solver_sympatht::iterate(
5757
// The path has been altered during computation (solver has found another
5858
// loop-select guard that can be true
5959
auto new_sympath=inner_solver->symbolic_path.get_expr();
60-
inv.emplace(new_sympath, inv.at(sympath));
60+
inv.emplace(new_sympath, std::move(inv.at(sympath)));
6161
inv.erase(sympath);
6262
symbolic_path=inner_solver->symbolic_path;
6363
#ifdef DEBUG
@@ -70,7 +70,8 @@ bool strategy_solver_sympatht::iterate(
7070
else
7171
{
7272
// Computing invariant for a new path
73-
auto new_value=inv.inner_value_template->clone();
73+
auto new_value=std::unique_ptr<domaint::valuet>(
74+
inv.inner_value_template->clone());
7475
domain.inner_domain->initialize_value(*new_value);
7576
improved=inner_solver->iterate(*new_value);
7677

@@ -82,7 +83,7 @@ bool strategy_solver_sympatht::iterate(
8283
std::cerr << from_expr(ns, "", symbolic_path.get_expr()) << "\n";
8384
#endif
8485
const exprt sympath=inner_solver->symbolic_path.get_expr();
85-
inv.emplace(sympath, new_value);
86+
inv.emplace(sympath, std::move(new_value));
8687
new_path=false;
8788
}
8889
}

src/domains/strategy_solver_sympath.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ class strategy_solver_sympatht:public strategy_solver_baset
2323
sympath_domaint &_domain,
2424
incremental_solvert &_solver,
2525
const local_SSAt &SSA,
26-
strategy_solver_baset *inner_solver):
26+
std::unique_ptr<strategy_solver_baset> _inner_solver):
2727
strategy_solver_baset(_solver, SSA.ns),
2828
domain(_domain),
29-
inner_solver(inner_solver)
29+
inner_solver(std::move(_inner_solver))
3030
{
3131
build_loop_conds_map(SSA);
3232
inner_solver->use_sympaths();
@@ -40,7 +40,7 @@ class strategy_solver_sympatht:public strategy_solver_baset
4040
sympath_domaint &domain;
4141

4242
// Strategy solver for the inner domain
43-
strategy_solver_baset *inner_solver;
43+
std::unique_ptr<strategy_solver_baset> inner_solver;
4444

4545
std::vector<symbolic_patht> visited_paths;
4646
bool new_path=true;

0 commit comments

Comments
 (0)