Skip to content

Commit a6b4072

Browse files
committed
type checking & conversion of loop assigns clauses
1 parent e3a84b6 commit a6b4072

File tree

4 files changed

+62
-34
lines changed

4 files changed

+62
-34
lines changed

src/ansi-c/c_typecheck_base.cpp

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -739,33 +739,7 @@ void c_typecheck_baset::typecheck_declaration(
739739
CPROVER_PREFIX "loop_entry is not allowed in preconditions.");
740740
}
741741

742-
for(auto &target : code_type.assigns())
743-
{
744-
typecheck_expr(target);
745-
746-
if(target.type().id() == ID_empty)
747-
{
748-
error().source_location = target.source_location();
749-
error() << "void-typed targets not permitted" << eom;
750-
throw 0;
751-
}
752-
else if(target.id() == ID_pointer_object)
753-
{
754-
// skip
755-
}
756-
else if(!target.get_bool(ID_C_lvalue))
757-
{
758-
error().source_location = target.source_location();
759-
error() << "illegal target in assigns clause" << eom;
760-
throw 0;
761-
}
762-
else if(has_subexpr(target, ID_side_effect))
763-
{
764-
error().source_location = target.source_location();
765-
error() << "assigns clause is not side-effect free" << eom;
766-
throw 0;
767-
}
768-
}
742+
typecheck_spec_assigns(code_type.assigns());
769743

770744
if(!as_const(code_type).ensures().empty())
771745
{

src/ansi-c/c_typecheck_base.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ class c_typecheck_baset:
144144
virtual void typecheck_while(code_whilet &code);
145145
virtual void typecheck_dowhile(code_dowhilet &code);
146146
virtual void typecheck_start_thread(codet &code);
147+
148+
// contracts
149+
virtual void typecheck_spec_assigns(exprt::operandst &targets);
147150
virtual void typecheck_spec_loop_invariant(codet &code);
148151
virtual void typecheck_spec_decreases(codet &code);
149152

src/ansi-c/c_typecheck_code.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Author: Daniel Kroening, [email protected]
1313

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

@@ -486,6 +487,10 @@ void c_typecheck_baset::typecheck_for(codet &code)
486487

487488
typecheck_spec_loop_invariant(code);
488489
typecheck_spec_decreases(code);
490+
491+
if(code.find(ID_C_spec_assigns).is_not_nil())
492+
typecheck_spec_assigns(
493+
static_cast<unary_exprt &>(code.add(ID_C_spec_assigns)).op().operands());
489494
}
490495

491496
void c_typecheck_baset::typecheck_label(code_labelt &code)
@@ -775,6 +780,10 @@ void c_typecheck_baset::typecheck_while(code_whilet &code)
775780

776781
typecheck_spec_loop_invariant(code);
777782
typecheck_spec_decreases(code);
783+
784+
if(code.find(ID_C_spec_assigns).is_not_nil())
785+
typecheck_spec_assigns(
786+
static_cast<unary_exprt &>(code.add(ID_C_spec_assigns)).op().operands());
778787
}
779788

780789
void c_typecheck_baset::typecheck_dowhile(code_dowhilet &code)
@@ -809,6 +818,41 @@ void c_typecheck_baset::typecheck_dowhile(code_dowhilet &code)
809818

810819
typecheck_spec_loop_invariant(code);
811820
typecheck_spec_decreases(code);
821+
822+
if(code.find(ID_C_spec_assigns).is_not_nil())
823+
typecheck_spec_assigns(
824+
static_cast<unary_exprt &>(code.add(ID_C_spec_assigns)).op().operands());
825+
}
826+
827+
void c_typecheck_baset::typecheck_spec_assigns(exprt::operandst &targets)
828+
{
829+
for(auto &target : targets)
830+
{
831+
typecheck_expr(target);
832+
833+
if(target.type().id() == ID_empty)
834+
{
835+
error().source_location = target.source_location();
836+
error() << "void-typed targets not permitted" << eom;
837+
throw 0;
838+
}
839+
else if(target.id() == ID_pointer_object)
840+
{
841+
// skip
842+
}
843+
else if(!target.get_bool(ID_C_lvalue))
844+
{
845+
error().source_location = target.source_location();
846+
error() << "illegal target in assigns clause" << eom;
847+
throw 0;
848+
}
849+
else if(has_subexpr(target, ID_side_effect))
850+
{
851+
error().source_location = target.source_location();
852+
error() << "assigns clause is not side-effect free" << eom;
853+
throw 0;
854+
}
855+
}
812856
}
813857

814858
void c_typecheck_baset::typecheck_spec_loop_invariant(codet &code)

src/goto-programs/goto_convert.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -863,11 +863,16 @@ void goto_convertt::convert_loop_contracts(
863863
goto_programt::targett loop,
864864
const irep_idt &mode)
865865
{
866-
exprt invariant =
867-
static_cast<const exprt &>(code.find(ID_C_spec_loop_invariant));
868-
exprt decreases_clause =
869-
static_cast<const exprt &>(code.find(ID_C_spec_decreases));
866+
auto assigns =
867+
static_cast<const unary_exprt &>(code.find(ID_C_spec_assigns));
868+
if(assigns.is_not_nil())
869+
{
870+
PRECONDITION(loop->is_goto());
871+
loop->guard.add(ID_C_spec_assigns).swap(assigns.op());
872+
}
870873

874+
auto invariant =
875+
static_cast<const exprt &>(code.find(ID_C_spec_loop_invariant));
871876
if(!invariant.is_nil())
872877
{
873878
if(has_subexpr(invariant, ID_side_effect))
@@ -880,6 +885,8 @@ void goto_convertt::convert_loop_contracts(
880885
loop->condition_nonconst().add(ID_C_spec_loop_invariant).swap(invariant);
881886
}
882887

888+
auto decreases_clause =
889+
static_cast<const exprt &>(code.find(ID_C_spec_decreases));
883890
if(!decreases_clause.is_nil())
884891
{
885892
if(has_subexpr(decreases_clause, ID_side_effect))
@@ -972,7 +979,7 @@ void goto_convertt::convert_for(
972979
goto_programt::targett y = tmp_y.add(
973980
goto_programt::make_goto(u, true_exprt(), code.source_location()));
974981

975-
// loop invariant and decreases clause
982+
// assigns clause, loop invariant and decreases clause
976983
convert_loop_contracts(code, y, mode);
977984

978985
dest.destructive_append(sideeffects);
@@ -1030,7 +1037,7 @@ void goto_convertt::convert_while(
10301037
goto_programt tmp_x;
10311038
convert(code.body(), tmp_x, mode);
10321039

1033-
// loop invariant and decreases clause
1040+
// assigns clause, loop invariant and decreases clause
10341041
convert_loop_contracts(code, y, mode);
10351042

10361043
dest.destructive_append(tmp_branch);
@@ -1099,7 +1106,7 @@ void goto_convertt::convert_dowhile(
10991106
// y: if(c) goto w;
11001107
y->complete_goto(w);
11011108

1102-
// loop invariant and decreases clause
1109+
// assigns_clause, loop invariant and decreases clause
11031110
convert_loop_contracts(code, y, mode);
11041111

11051112
dest.destructive_append(tmp_w);

0 commit comments

Comments
 (0)