Skip to content

Commit 057fe4e

Browse files
authored
Merge pull request #7214 from remi-delmas-3000/contracts-assigns-clause-allow-all-void-function-calls
CONTRACTS: Allow void function calls in assigns clauses
2 parents 0f4353f + 8601666 commit 057fe4e

File tree

14 files changed

+67
-38
lines changed

14 files changed

+67
-38
lines changed

regression/contracts/assigns_enforce_address_of/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--enforce-contract foo
44
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
6+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
77
^CONVERSION ERROR$
88
--
99
--

regression/contracts/assigns_enforce_conditional_non_lvalue_target/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
main.c
33
--enforce-contract foo
4-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
4+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
55
^CONVERSION ERROR
66
^EXIT=(1|64)$
77
^SIGNAL=0$

regression/contracts/assigns_enforce_conditional_non_lvalue_target_list/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
main.c
33
--enforce-contract foo
4-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
4+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
55
^CONVERSION ERROR
66
^EXIT=(1|64)$
77
^SIGNAL=0$

regression/contracts/assigns_enforce_function_calls/main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,4 @@ int main()
1313
{
1414
int x;
1515
foo(&x);
16-
baz(&x);
1716
}

regression/contracts/assigns_enforce_function_calls/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ main.c
33
--enforce-contract foo
44
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
6+
^.*error: expecting void return type for function 'bar' called in assigns clause$
77
^CONVERSION ERROR$
88
--
99
--
10-
Check that function call expressions are rejected in assigns clauses.
10+
Check that non-void function call expressions are rejected in assigns clauses.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
void bar(int *x)
2+
{
3+
if(x)
4+
__CPROVER_typed_target(x);
5+
}
6+
7+
int foo(int *x) __CPROVER_assigns(bar(x))
8+
{
9+
*x = 0;
10+
return 0;
11+
}
12+
13+
int main()
14+
{
15+
int x;
16+
foo(&x);
17+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main.c
3+
--enforce-contract foo
4+
^call to function 'bar' in assigns clause not supported yet$
5+
^EXIT=(127|134)$
6+
^SIGNAL=0$
7+
--
8+
--
9+
Check that void function call expressions in assigns clauses make
10+
instrumentation fail.

regression/contracts/assigns_enforce_literal/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--enforce-contract foo
44
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
6+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
77
^CONVERSION ERROR$
88
--
99
--

regression/contracts/assigns_enforce_side_effects_2/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--enforce-contract foo
44
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
6+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
77
^CONVERSION ERROR$
88
--
99
--

regression/contracts/assigns_enforce_side_effects_3/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ main.c
33
--enforce-contract foo
44
^EXIT=(1|64)$
55
^SIGNAL=0$
6-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
6+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
77
^CONVERSION ERROR$
88
--
99
--

regression/contracts/assigns_type_checking_invalid_case_01/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ main.c
44
^EXIT=(1|64)$
55
^SIGNAL=0$
66
^CONVERSION ERROR$
7-
^.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
7+
^.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
88
--
99
Checks whether type checking rejects literal constants in assigns clause.

regression/contracts/reject_history_expr_in_assigns_clause/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
main.c
33
--enforce-contract foo
4-
^main.c.*error: assigns clause target must be a non-void lvalue or a call to one of __CPROVER_POINTER_OBJECT, __CPROVER_assignable, __CPROVER_object_whole, __CPROVER_object_upto, __CPROVER_object_from$
4+
^main.c.*error: assigns clause target must be a non-void lvalue, a call to __CPROVER_POINTER_OBJECT or a call to a function returning void$
55
^CONVERSION ERROR$
66
^EXIT=(1|64)$
77
^SIGNAL=0$

src/ansi-c/c_typecheck_code.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -995,34 +995,34 @@ void c_typecheck_baset::typecheck_spec_assigns_target(exprt &target)
995995
else if(can_cast_expr<side_effect_expr_function_callt>(target))
996996
{
997997
const auto &funcall = to_side_effect_expr_function_call(target);
998-
if(can_cast_expr<symbol_exprt>(funcall.function()))
998+
if(!can_cast_expr<symbol_exprt>(funcall.function()))
999999
{
1000-
const auto &ident = to_symbol_expr(funcall.function()).get_identifier();
1001-
if(
1002-
ident == CPROVER_PREFIX "assignable" ||
1003-
ident == CPROVER_PREFIX "object_whole" ||
1004-
ident == CPROVER_PREFIX "object_upto" ||
1005-
ident == CPROVER_PREFIX "object_from")
1006-
{
1007-
for(const auto &argument : funcall.arguments())
1008-
throw_on_side_effects(argument);
1009-
return;
1010-
}
1000+
throw invalid_source_file_exceptiont(
1001+
"function pointer calls not allowed in assigns clauses",
1002+
target.source_location());
10111003
}
1012-
else
1004+
1005+
if(target.type().id() != ID_empty)
10131006
{
10141007
throw invalid_source_file_exceptiont(
1015-
"function pointer calls not allowed in assigns clauses",
1008+
"expecting void return type for function '" +
1009+
id2string(to_symbol_expr(funcall.function()).get_identifier()) +
1010+
"' called in assigns clause",
10161011
target.source_location());
10171012
}
1013+
1014+
for(const auto &argument : funcall.arguments())
1015+
throw_on_side_effects(argument);
1016+
}
1017+
else
1018+
{
1019+
// if we reach this point the target did not pass the checks
1020+
throw invalid_source_file_exceptiont(
1021+
"assigns clause target must be a non-void lvalue, a call "
1022+
"to " CPROVER_PREFIX
1023+
"POINTER_OBJECT or a call to a function returning void",
1024+
target.source_location());
10181025
}
1019-
// if we reach this point the target did not pass the checks
1020-
throw invalid_source_file_exceptiont(
1021-
"assigns clause target must be a non-void lvalue or a call to one "
1022-
"of " CPROVER_PREFIX "POINTER_OBJECT, " CPROVER_PREFIX
1023-
"assignable, " CPROVER_PREFIX "object_whole, " CPROVER_PREFIX
1024-
"object_upto, " CPROVER_PREFIX "object_from",
1025-
target.source_location());
10261026
}
10271027

10281028
void c_typecheck_baset::typecheck_spec_function_pointer_obeys_contract(

src/goto-instrument/contracts/instrument_spec_assigns.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,15 @@ car_exprt instrument_spec_assignst::create_car_expr(
487487
if(can_cast_expr<symbol_exprt>(funcall.function()))
488488
{
489489
const auto &ident = to_symbol_expr(funcall.function()).get_identifier();
490+
491+
PRECONDITION_WITH_DIAGNOSTICS(
492+
ident == CPROVER_PREFIX "object_from" ||
493+
ident == CPROVER_PREFIX "object_upto" ||
494+
ident == CPROVER_PREFIX "object_whole" ||
495+
ident == CPROVER_PREFIX "assignable",
496+
"call to function '" + id2string(ident) +
497+
"' in assigns clause not supported yet");
498+
490499
if(ident == CPROVER_PREFIX "object_from")
491500
{
492501
const auto &ptr = funcall.arguments().at(0);
@@ -558,12 +567,6 @@ car_exprt instrument_spec_assignst::create_car_expr(
558567
is_ptr_to_ptr.is_true() ? car_havoc_methodt::NONDET_ASSIGN
559568
: car_havoc_methodt::HAVOC_SLICE};
560569
}
561-
else
562-
{
563-
log.error().source_location = target.source_location();
564-
log.error() << "call to " << ident
565-
<< " in assigns clauses not supported in this version";
566-
}
567570
}
568571
}
569572
else if(is_assignable(target))

0 commit comments

Comments
 (0)