@@ -644,19 +644,6 @@ void c_typecheck_baset::typecheck_declaration(
644644 // mark as 'already typechecked'
645645 already_typechecked_typet::make_already_typechecked (declaration.type ());
646646
647- irept contract;
648-
649- {
650- exprt spec_assigns = declaration.spec_assigns ();
651- contract.add (ID_C_spec_assigns).swap (spec_assigns);
652-
653- exprt spec_ensures = declaration.spec_ensures ();
654- contract.add (ID_C_spec_ensures).swap (spec_ensures);
655-
656- exprt spec_requires = declaration.spec_requires ();
657- contract.add (ID_C_spec_requires).swap (spec_requires);
658- }
659-
660647 // Now do declarators, if any.
661648 for (auto &declarator : declaration.declarators ())
662649 {
@@ -728,45 +715,45 @@ void c_typecheck_baset::typecheck_declaration(
728715 irep_idt identifier=symbol.name ;
729716 declarator.set_name (identifier);
730717
731- // If the declarator is for a function definition, typecheck it.
732- if (can_cast_type<code_typet>(declarator.type ()))
733- {
734- typecheck_assigns (to_code_type (declarator.type ()), contract);
735- }
736-
737718 typecheck_symbol (symbol);
738719
739- // add code contract (if any); we typecheck this after the
740- // function body done above, so as to have parameter symbols
741- // available
720+ // check the contract, if any
742721 symbolt &new_symbol = symbol_table.get_writeable_ref (identifier);
722+ if (new_symbol.type .id () == ID_code)
723+ {
724+ // We typecheck this after the
725+ // function body done above, so as to have parameter symbols
726+ // available
727+ auto &code_type = to_code_with_contract_type (new_symbol.type );
728+
729+ if (as_const (code_type).requires ().is_not_nil ())
730+ {
731+ auto &requires = code_type.requires ();
732+ typecheck_expr (requires );
733+ implicit_typecast_bool (requires );
734+ }
735+
736+ if (as_const (code_type).assigns ().is_not_nil ())
737+ {
738+ for (auto &op : code_type.assigns ().operands ())
739+ typecheck_expr (op);
740+ }
743741
744- typecheck_assigns_exprs (
745- static_cast <codet &>(contract), ID_C_spec_assigns);
746- typecheck_spec_expr (static_cast <codet &>(contract), ID_C_spec_requires);
747-
748- typet ret_type = void_type ();
749- if (new_symbol.type .id ()==ID_code)
750- ret_type=to_code_type (new_symbol.type ).return_type ();
751- assert (parameter_map.empty ());
752- if (ret_type.id ()!=ID_empty)
753- parameter_map[CPROVER_PREFIX " return_value" ] = ret_type;
754- typecheck_spec_expr (static_cast <codet &>(contract), ID_C_spec_ensures);
755- parameter_map.clear ();
756-
757- exprt assigns_to_add =
758- static_cast <const exprt &>(contract.find (ID_C_spec_assigns));
759- if (assigns_to_add.is_not_nil ())
760- to_code_with_contract_type (new_symbol.type ).assigns () = assigns_to_add;
761- exprt requires_to_add =
762- static_cast <const exprt &>(contract.find (ID_C_spec_requires));
763- if (requires_to_add.is_not_nil ())
764- to_code_with_contract_type (new_symbol.type ).requires () =
765- requires_to_add;
766- exprt ensures_to_add =
767- static_cast <const exprt &>(contract.find (ID_C_spec_ensures));
768- if (ensures_to_add.is_not_nil ())
769- to_code_with_contract_type (new_symbol.type ).ensures () = ensures_to_add;
742+ if (as_const (code_type).ensures ().is_not_nil ())
743+ {
744+ const auto &return_type = code_type.return_type ();
745+
746+ if (return_type.id () != ID_empty)
747+ parameter_map[CPROVER_PREFIX " return_value" ] = return_type;
748+
749+ auto &ensures = code_type.ensures ();
750+ typecheck_expr (ensures);
751+ implicit_typecast_bool (ensures);
752+
753+ if (return_type.id () != ID_empty)
754+ parameter_map.erase (CPROVER_PREFIX " return_value" );
755+ }
756+ }
770757 }
771758 }
772759}
0 commit comments