@@ -601,8 +601,31 @@ bool code_contractst::apply_function_contract(
601601 // in the assigns clause.
602602 if (assigns.is_not_nil ())
603603 {
604- assigns_clauset assigns_cause (assigns, log, ns);
605- auto assigns_havoc = assigns_cause.generate_havoc_code ();
604+ assigns_clauset assigns_clause (assigns, log, ns);
605+
606+ // Retrieve assigns clause of the caller function if exists.
607+ const irep_idt &caller_function = target->source_location .get_function ();
608+ auto caller_assigns =
609+ to_code_with_contract_type (ns.lookup (caller_function).type ).assigns ();
610+
611+ if (caller_assigns.is_not_nil ())
612+ {
613+ // check subset relationship of assigns clause for called function
614+ assigns_clauset caller_assigns_clause (caller_assigns, log, ns);
615+ goto_programt subset_check_assertion;
616+ subset_check_assertion.add (goto_programt::make_assertion (
617+ caller_assigns_clause.generate_subset_check (assigns_clause),
618+ assigns_clause.location ));
619+ subset_check_assertion.instructions .back ().source_location .set_comment (
620+ " Check that " + id2string (function) +
621+ " 's assigns clause is a subset of " + id2string (caller_function) +
622+ " 's assigns clause" );
623+ insert_before_swap_and_advance (
624+ goto_program, target, subset_check_assertion);
625+ }
626+
627+ // Havoc all targets in global write set
628+ auto assigns_havoc = assigns_clause.generate_havoc_code ();
606629
607630 // Insert the non-deterministic assignment immediately before the call site.
608631 insert_before_swap_and_advance (goto_program, target, assigns_havoc);
@@ -772,8 +795,8 @@ void code_contractst::instrument_call_statement(
772795 alias_assertion.instructions .back ().source_location .set_comment (
773796 " Check that " + from_expr (ns, alias_expr.id (), alias_expr) +
774797 " is assignable" );
775- program. insert_before_swap (instruction_iterator, alias_assertion);
776- ++ instruction_iterator;
798+ insert_before_swap_and_advance (
799+ program, instruction_iterator, alias_assertion) ;
777800 }
778801
779802 const symbolt &called_symbol = ns.lookup (called_name);
@@ -810,9 +833,12 @@ void code_contractst::instrument_call_statement(
810833 alias_assertion.add (goto_programt::make_assertion (
811834 subset_check, instruction_iterator->source_location ));
812835 alias_assertion.instructions .back ().source_location .set_comment (
813- " Check that callee's assigns clause is a subset of caller's" );
814- program.insert_before_swap (instruction_iterator, alias_assertion);
815- ++instruction_iterator;
836+ " Check that " + id2string (called_name) +
837+ " 's assigns clause is a subset of " +
838+ id2string (instruction_iterator->source_location .get_function ()) +
839+ " 's assigns clause" );
840+ insert_before_swap_and_advance (
841+ program, instruction_iterator, alias_assertion);
816842 }
817843}
818844
0 commit comments