@@ -20,8 +20,6 @@ Date: May 2016
2020#include < util/options.h>
2121
2222#include " cover_basic_blocks.h"
23- #include " cover_filter.h"
24- #include " cover_instrument.h"
2523
2624// / Applies instrumenters to given goto program
2725// / \param goto_program: the goto program
@@ -165,91 +163,53 @@ void parse_cover_options(const cmdlinet &cmdline, optionst &options)
165163 cmdline.isset (" cover-traces-must-terminate" ));
166164}
167165
168- // / Applies instrumenters to given goto functions
169- // / \param goto_functions: the goto functions
170- // / \param instrumenters: the instrumenters
171- // / \param function_filters: function filters to discard certain functions
172- // / \param message_handler: a message handler
173- void instrument_cover_goals (
174- goto_functionst &goto_functions,
175- const cover_instrumenterst &instrumenters,
176- const function_filterst &function_filters,
177- message_handlert &message_handler)
178- {
179- Forall_goto_functions (f_it, goto_functions)
180- {
181- if (!function_filters (f_it->first , f_it->second ))
182- continue ;
183-
184- instrument_cover_goals (f_it->second .body , instrumenters, message_handler);
185- }
186- }
187-
188- // / Instruments goto functions based on given command line options
189- // / \param options: the options
190- // / \param symbol_table: the symbol table
191- // / \param goto_functions: the goto functions
192- // / \param message_handler: a message handler
193- bool instrument_cover_goals (
166+ // / Build data structures controlling coverage from command-line options.
167+ // / \param options: command-line options
168+ // / \param symbol_table: global symbol table
169+ // / \param message_handler: used to log incorrect option specifications
170+ // / \return a cover_configt on success, or null otherwise.
171+ std::unique_ptr<cover_configt> get_cover_config (
194172 const optionst &options,
195173 const symbol_tablet &symbol_table,
196- goto_functionst &goto_functions,
197174 message_handlert &message_handler)
198175{
199176 messaget msg (message_handler);
177+ std::unique_ptr<cover_configt> config = util_make_unique<cover_configt>();
178+ function_filterst &function_filters = config->function_filters ;
179+ goal_filterst &goal_filters = config->goal_filters ;
180+ cover_instrumenterst &instrumenters = config->cover_instrumenters ;
200181
201- function_filterst function_filters;
202182 function_filters.add (
203183 util_make_unique<internal_functions_filtert>(message_handler));
204184
205- goal_filterst goal_filters;
206185 goal_filters.add (util_make_unique<internal_goals_filtert>(message_handler));
207186
208- cover_instrumenterst instrumenters;
209-
210187 optionst::value_listt criteria_strings = options.get_list_option (" cover" );
211- bool keep_assertions=false ;
212188
189+ config->keep_assertions = false ;
213190 for (const auto &criterion_string : criteria_strings)
214191 {
215192 try
216193 {
217194 coverage_criteriont c = parse_coverage_criterion (criterion_string);
218195
219196 if (c == coverage_criteriont::ASSERTION)
220- keep_assertions = true ;
197+ config-> keep_assertions = true ;
221198
222199 instrumenters.add_from_criterion (c, symbol_table, goal_filters);
223200 }
224201 catch (const std::string &e)
225202 {
226203 msg.error () << e << messaget::eom;
227- return true ;
204+ return {} ;
228205 }
229206 }
230207
231- if (keep_assertions && criteria_strings.size ()>1 )
208+ if (config-> keep_assertions && criteria_strings.size ()>1 )
232209 {
233210 msg.error () << " assertion coverage cannot currently be used together with "
234211 << " other coverage criteria" << messaget::eom;
235- return true ;
236- }
237-
238- msg.status () << " Rewriting existing assertions as assumptions"
239- << messaget::eom;
240-
241- if (!keep_assertions)
242- {
243- // turn assertions (from generic checks) into assumptions
244- Forall_goto_functions (f_it, goto_functions)
245- {
246- goto_programt &body=f_it->second .body ;
247- Forall_goto_program_instructions (i_it, body)
248- {
249- if (i_it->is_assert ())
250- i_it->type =goto_program_instruction_typet::ASSUME;
251- }
252- }
212+ return {};
253213 }
254214
255215 // cover entry point function only
@@ -266,32 +226,108 @@ bool instrument_cover_goals(
266226 function_filters.add (
267227 util_make_unique<trivial_functions_filtert>(message_handler));
268228
269- msg.status () << " Instrumenting coverage goals" << messaget::eom;
270-
271- instrument_cover_goals (
272- goto_functions, instrumenters, function_filters, message_handler);
229+ config->traces_must_terminate =
230+ options.get_bool_option (" cover-traces-must-terminate" );
273231
274- function_filters. report_anomalies () ;
275- goal_filters. report_anomalies ();
232+ return config ;
233+ }
276234
277- if (options.get_bool_option (" cover-traces-must-terminate" ))
235+ // / Instruments a single goto program based on the given configuration
236+ // / \param config: configuration, produced using get_cover_config
237+ // / \param function_id: function name
238+ // / \param function: function function to instrument
239+ // / \param message_handler: log output
240+ static void instrument_cover_goals (
241+ const cover_configt &config,
242+ const irep_idt &function_id,
243+ goto_functionst::goto_functiont &function,
244+ message_handlert &message_handler)
245+ {
246+ if (!config.keep_assertions )
278247 {
279- // instrument an additional goal in CPROVER_START. This will rephrase
280- // the reachability problem by asking BMC to provide a solution that
281- // satisfies a goal while getting to the end of the program-under-test.
282- const auto sf_it=
283- goto_functions.function_map .find (goto_functions.entry_point ());
284- if (sf_it==goto_functions.function_map .end ())
248+ Forall_goto_program_instructions (i_it, function.body )
285249 {
286- msg.error () << " cover-traces-must-terminate: invalid entry point ["
287- << goto_functions.entry_point () << " ]" << messaget::eom;
288- return true ;
250+ if (i_it->is_assert ())
251+ i_it->type =goto_program_instruction_typet::ASSUME;
289252 }
253+ }
254+
255+ bool changed = false ;
290256
291- cover_instrument_end_of_function (sf_it->first , sf_it->second .body );
257+ if (config.function_filters (function_id, function))
258+ {
259+ instrument_cover_goals (
260+ function.body , config.cover_instrumenters , message_handler);
261+ changed = true ;
262+ }
263+
264+ if (config.traces_must_terminate &&
265+ function_id == goto_functionst::entry_point ())
266+ {
267+ cover_instrument_end_of_function (function_id, function.body );
268+ changed = true ;
269+ }
270+
271+ if (changed)
272+ function.body .update ();
273+ }
274+
275+ // / Instruments a single goto program based on the given configuration
276+ // / \param config: configuration, produced using get_cover_config
277+ // / \param function: goto program to instrument
278+ // / \param message_handler: log output
279+ void instrument_cover_goals (
280+ const cover_configt &config,
281+ goto_model_functiont &function,
282+ message_handlert &message_handler)
283+ {
284+ instrument_cover_goals (
285+ config,
286+ function.get_function_id (),
287+ function.get_goto_function (),
288+ message_handler);
289+
290+ function.compute_location_numbers ();
291+ }
292+
293+ // / Instruments goto functions based on given command line options
294+ // / \param options: the options
295+ // / \param symbol_table: the symbol table
296+ // / \param goto_functions: the goto functions
297+ // / \param message_handler: a message handler
298+ bool instrument_cover_goals (
299+ const optionst &options,
300+ const symbol_tablet &symbol_table,
301+ goto_functionst &goto_functions,
302+ message_handlert &message_handler)
303+ {
304+ messaget msg (message_handler);
305+ msg.status () << " Rewriting existing assertions as assumptions"
306+ << messaget::eom;
307+
308+ std::unique_ptr<cover_configt> config =
309+ get_cover_config (options, symbol_table, message_handler);
310+ if (!config)
311+ return true ;
312+
313+ if (config->traces_must_terminate &&
314+ !goto_functions.function_map .count (goto_functions.entry_point ()))
315+ {
316+ msg.error () << " cover-traces-must-terminate: invalid entry point ["
317+ << goto_functions.entry_point () << " ]" << messaget::eom;
318+ return true ;
292319 }
293320
294- goto_functions.update ();
321+ Forall_goto_functions (f_it, goto_functions)
322+ {
323+ instrument_cover_goals (
324+ *config, f_it->first , f_it->second , message_handler);
325+ }
326+ goto_functions.compute_location_numbers ();
327+
328+ config->function_filters .report_anomalies ();
329+ config->goal_filters .report_anomalies ();
330+
295331 return false ;
296332}
297333
0 commit comments