cprover
Loading...
Searching...
No Matches
dfcc_contract_handler.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Dynamic frame condition checking for function contracts
4
5Author: Remi Delmas, delmasrd@amazon.com
6Date: August 2022
7
8\*******************************************************************/
9
11
14
16
17#include "dfcc_utils.h"
19
20std::map<irep_idt, dfcc_contract_functionst>
22
42
45{
46 auto iter = dfcc_contract_handlert::contract_cache.find(contract_id);
47
48 // return existing value
50 return iter->second;
51
52 // insert new value
54 .insert(
55 {contract_id,
57 get_pure_contract_symbol(contract_id),
60 library,
63 instrument)})
64 .first->second;
65}
66
67const std::size_t
72
74 const dfcc_contract_modet contract_mode,
75 const irep_idt &wrapper_id,
76 const irep_idt &wrapped_id,
77 const irep_idt &contract_id,
78 const symbolt &wrapper_write_set_symbol,
79 goto_programt &dest,
80 std::set<irep_idt> &function_pointer_contracts)
81{
83 contract_mode,
84 dfcc_utilst::get_function_symbol(goto_model.symbol_table, wrapper_id),
85 dfcc_utilst::get_function_symbol(goto_model.symbol_table, wrapped_id),
86 get_contract_functions(contract_id),
87 wrapper_write_set_symbol,
90 library,
93 .add_to_dest(dest, function_pointer_contracts);
94}
95
97 const irep_idt &contract_id,
98 const std::optional<irep_idt> function_id_opt)
99{
100 auto pure_contract_id = "contract::" + id2string(contract_id);
101 const symbolt *pure_contract_symbol = nullptr;
102 if(!ns.lookup(pure_contract_id, pure_contract_symbol))
103 {
104 if(function_id_opt.has_value())
105 {
106 auto function_id = function_id_opt.value();
107 const auto &function_symbol =
108 dfcc_utilst::get_function_symbol(goto_model.symbol_table, function_id);
110 function_id,
111 to_code_type(function_symbol.type),
112 pure_contract_id,
113 to_code_type(pure_contract_symbol->type));
114 }
115 return *pure_contract_symbol;
116 }
117 else
118 {
119 // The contract symbol might not have been created if the function had
120 // no contract or a contract with all empty clauses (which is equivalent).
121 // in that case we create a fresh symbol again with empty clauses.
123 function_id_opt.has_value(),
124 "Contract '" + pure_contract_id +
125 "' not found, the identifier of an existing function must be provided "
126 "to derive a default contract");
127
128 auto function_id = function_id_opt.value();
129 const auto &function_symbol =
130 dfcc_utilst::get_function_symbol(goto_model.symbol_table, function_id);
131
132 log.warning() << "Contract '" << contract_id
133 << "' not found, deriving empty pure contract '"
134 << pure_contract_id << "' from function '" << function_id
135 << "'" << messaget::eom;
136
137 symbolt new_symbol{
138 pure_contract_id, function_symbol.type, function_symbol.mode};
139 new_symbol.base_name = pure_contract_id;
140 new_symbol.pretty_name = pure_contract_id;
141 new_symbol.is_property = true;
142 new_symbol.module = function_symbol.module;
143 new_symbol.location = function_symbol.location;
144 auto entry = goto_model.symbol_table.insert(std::move(new_symbol));
145 INVARIANT(
146 entry.second,
147 "contract '" + id2string(function_symbol.display_name()) +
148 "' already set at " + id2string(entry.first.location.as_string()));
149 // this lookup will work and set the pointer
150 // no need to check for signature compatibility
151 ns.lookup(pure_contract_id, pure_contract_symbol);
152 return *pure_contract_symbol;
153 }
154}
155
157 const irep_idt &contract_id,
158 const code_typet &contract_type,
159 const irep_idt &pure_contract_id,
160 const code_typet &pure_contract_type)
161{
162 // can we turn a call to `contract` into a call to `pure_contract` ?
163 bool compatible =
164 function_is_type_compatible(true, contract_type, pure_contract_type, ns);
165
166 if(!compatible)
167 {
168 std::ostringstream err_msg;
169 err_msg << "dfcc_contract_handlert: function '" << contract_id
170 << "' and the corresponding pure contract symbol '"
171 << pure_contract_id << "' have incompatible type signatures:\n";
172
173 err_msg << "- contract return type "
174 << from_type(ns, contract_id, contract_type.return_type()) << "\n";
175
176 for(const auto &param : contract_type.parameters())
177 {
178 err_msg << "- contract param type "
179 << from_type(ns, contract_id, param.type()) << "\n";
180 }
181
182 err_msg << "- pure contract return type "
183 << from_type(ns, pure_contract_id, pure_contract_type.return_type())
184 << "\n";
185
186 for(const auto &param : pure_contract_type.parameters())
187 {
188 err_msg << "- pure contract param type "
189 << from_type(ns, pure_contract_id, param.type()) << "\n";
190 }
191
192 err_msg << "aborting."
193 << "\n";
195 err_msg.str(), contract_type.source_location());
196 }
197}
Base type of functions.
Definition std_types.h:583
const parameterst & parameters() const
Definition std_types.h:699
const typet & return_type() const
Definition std_types.h:689
Translates assigns and frees clauses of a function contract or loop contract into GOTO programs that ...
Generates GOTO functions modelling a contract assigns and frees clauses.
const std::size_t get_nof_assigns_targets() const
Returns the maximum number of targets in the assigns clause.
void check_signature_compat(const irep_idt &contract_id, const code_typet &contract_type, const irep_idt &pure_contract_id, const code_typet &pure_contract_type)
Throws an error if the type signatures are not compatible.
dfcc_spec_functionst & spec_functions
const symbolt & get_pure_contract_symbol(const irep_idt &contract_id, const std::optional< irep_idt > function_id_opt={})
Searches for a symbol named "contract::contract_id" in the symbol table.
static std::map< irep_idt, dfcc_contract_functionst > contract_cache
dfcc_lift_memory_predicatest & memory_predicates
message_handlert & message_handler
dfcc_contract_clauses_codegent & contract_clauses_codegen
const std::size_t get_assigns_clause_size(const irep_idt &contract_id)
Returns the size assigns clause of the given contract in number of targets.
void add_contract_instructions(const dfcc_contract_modet contract_mode, const irep_idt &wrapper_id, const irep_idt &wrapped_id, const irep_idt &contract_id, const symbolt &wrapper_write_set_symbol, goto_programt &dest, std::set< irep_idt > &function_pointer_contracts)
Adds instructions in dest modeling contract checking, assuming that ret_t wrapper_id(params) is the f...
dfcc_contract_handlert(goto_modelt &goto_model, message_handlert &message_handler, dfcc_libraryt &library, dfcc_instrumentt &instrument, dfcc_lift_memory_predicatest &memory_predicates, dfcc_spec_functionst &spec_functions, dfcc_contract_clauses_codegent &contract_clauses_codegen)
const dfcc_contract_functionst & get_contract_functions(const irep_idt &contract_id)
Returns the dfcc_contract_functionst object for the given contract from the cache,...
This class instruments GOTO functions or instruction sequences for frame condition checking and loop ...
Class interface to library types and functions defined in cprover_contracts.c.
This class rewrites GOTO functions that use the built-ins:
Generates the body of a wrapper function from a contract specified using requires,...
void add_to_dest(goto_programt &dest, std::set< irep_idt > &dest_fp_contracts)
Adds the whole program to dest and the discovered function pointer contracts dest_fp_contracts.
A generic container class for the GOTO intermediate representation of one function.
Thrown when we can't handle something in an input source file.
static eomt eom
Definition message.h:289
Symbol table entry.
Definition symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition symbol.h:46
irep_idt module
Name of module the symbol belongs to.
Definition symbol.h:43
bool is_property
Definition symbol.h:67
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
typet type
Type of symbol.
Definition symbol.h:31
irep_idt pretty_name
Language-specific display name.
Definition symbol.h:52
const source_locationt & source_location() const
Definition type.h:72
Specialisation of dfcc_contract_handlert for contracts.
dfcc_contract_modet
Enum type representing the contract checking and replacement modes.
Dynamic frame condition checking utility functions.
Generates the body of a wrapper function from a contract for contract checking or contract replacemen...
Symbol Table + CFG.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
bool function_is_type_compatible(bool return_value_used, const code_typet &call_type, const code_typet &function_type, const namespacet &ns)
Returns true iff call_type can be converted to produce a function call of the same type as function_t...
Remove Indirect Function Calls.
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
Definition invariant.h:464
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
static symbolt & get_function_symbol(symbol_table_baset &, const irep_idt &function_id)
Returns the symbolt for function_id.
dstringt irep_idt