Skip to content

Commit 923c623

Browse files
committed
Properly track assigns clause targets in goto converter
Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
1 parent 1ab9590 commit 923c623

File tree

5 files changed

+23
-36
lines changed

5 files changed

+23
-36
lines changed

src/ansi-c/ansi_c_convert_type.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com
1313

1414
#include <util/c_types.h>
1515
#include <util/config.h>
16+
#include <util/expr_util.h>
1617
#include <util/std_types.h>
1718
#include <util/string_constant.h>
1819

@@ -253,26 +254,22 @@ void ansi_c_convert_typet::read_rec(const typet &type)
253254
const exprt &as_expr =
254255
static_cast<const exprt &>(static_cast<const irept &>(type));
255256

256-
for(const exprt &operand : to_unary_expr(as_expr).op().operands())
257+
for(const exprt &target : to_unary_expr(as_expr).op().operands())
257258
{
258-
if(
259-
operand.id() != ID_symbol && operand.id() != ID_ptrmember &&
260-
operand.id() != ID_member && operand.id() != ID_dereference)
259+
if(!is_lvalue(target))
261260
{
262-
error().source_location = source_location;
261+
error().source_location = target.source_location();
263262
error() << "illegal target in assigns clause" << eom;
264263
throw 0;
265264
}
265+
else if(has_subexpr(target, ID_side_effect))
266+
{
267+
error().source_location = target.source_location();
268+
error() << "Assigns clause is not side-effect free." << eom;
269+
throw 0;
270+
}
271+
assigns.push_back(target);
266272
}
267-
268-
if(assigns.is_nil())
269-
assigns = to_unary_expr(as_expr).op();
270-
else
271-
{
272-
for(auto &assignment : to_unary_expr(as_expr).op().operands())
273-
assigns.add_to_operands(std::move(assignment));
274-
}
275-
assigns.add_source_location() = as_expr.source_location();
276273
}
277274
else if(type.id() == ID_C_spec_ensures)
278275
{
@@ -329,7 +326,7 @@ void ansi_c_convert_typet::write(typet &type)
329326
if(!requires.empty())
330327
to_code_with_contract_type(type).requires() = std::move(requires);
331328

332-
if(assigns.is_not_nil())
329+
if(!assigns.empty())
333330
to_code_with_contract_type(type).assigns() = std::move(assigns);
334331

335332
if(!ensures.empty())

src/ansi-c/ansi_c_convert_type.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ class ansi_c_convert_typet:public messaget
4747
bool constructor, destructor;
4848

4949
// contracts
50-
exprt assigns;
51-
exprt::operandst requires, ensures;
50+
exprt::operandst assigns, ensures, requires;
5251

5352
// storage spec
5453
c_storage_spect c_storage_spec;
@@ -87,7 +86,7 @@ class ansi_c_convert_typet:public messaget
8786
msc_based.make_nil();
8887
gcc_attribute_mode.make_nil();
8988

90-
assigns.make_nil();
89+
assigns.clear();
9190
requires.clear();
9291
ensures.clear();
9392

src/ansi-c/c_typecheck_base.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,10 +741,10 @@ void c_typecheck_baset::typecheck_declaration(
741741
}
742742
}
743743

744-
if(as_const(code_type).assigns().is_not_nil())
744+
if(!as_const(code_type).assigns().empty())
745745
{
746-
for(auto &op : code_type.assigns().operands())
747-
typecheck_expr(op);
746+
for(auto &target : code_type.assigns())
747+
typecheck_expr(target);
748748
}
749749

750750
if(!as_const(code_type).ensures().empty())

src/ansi-c/expr2c.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,10 +583,9 @@ std::string expr2ct::convert_rec(
583583
dest += " [[requires " + convert(requires) + "]]";
584584
}
585585

586-
if(!to_code_with_contract_type(src).assigns().operands().empty())
586+
for(auto &assigns : to_code_with_contract_type(src).assigns())
587587
{
588-
dest += " [[assigns " +
589-
convert(to_code_with_contract_type(src).assigns()) + "]]";
588+
dest += " [[assigns " + convert(assigns) + "]]";
590589
}
591590

592591
for(auto &ensures : to_code_with_contract_type(src).ensures())

src/util/c_types.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -339,22 +339,14 @@ class code_with_contract_typet : public code_typet
339339
{
340340
}
341341

342-
bool has_contract() const
342+
const exprt::operandst &assigns() const
343343
{
344-
return assigns().is_not_nil() || !requires().empty() || !ensures().empty();
344+
return static_cast<const exprt &>(find(ID_C_spec_assigns)).operands();
345345
}
346346

347-
const exprt &assigns() const
347+
exprt::operandst &assigns()
348348
{
349-
return static_cast<const exprt &>(find(ID_C_spec_assigns));
350-
}
351-
352-
exprt &assigns()
353-
{
354-
auto &result = static_cast<exprt &>(add(ID_C_spec_assigns));
355-
if(result.id().empty()) // not initialized?
356-
result.make_nil();
357-
return result;
349+
return static_cast<exprt &>(add(ID_C_spec_assigns)).operands();
358350
}
359351

360352
const exprt::operandst &requires() const

0 commit comments

Comments
 (0)