@@ -20,8 +20,6 @@ Date: May 2016
20
20
#include < util/options.h>
21
21
22
22
#include " cover_basic_blocks.h"
23
- #include " cover_filter.h"
24
- #include " cover_instrument.h"
25
23
26
24
// / Applies instrumenters to given goto program
27
25
// / \param goto_program: the goto program
@@ -165,91 +163,53 @@ void parse_cover_options(const cmdlinet &cmdline, optionst &options)
165
163
cmdline.isset (" cover-traces-must-terminate" ));
166
164
}
167
165
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 (
194
172
const optionst &options,
195
173
const symbol_tablet &symbol_table,
196
- goto_functionst &goto_functions,
197
174
message_handlert &message_handler)
198
175
{
199
176
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 ;
200
181
201
- function_filterst function_filters;
202
182
function_filters.add (
203
183
util_make_unique<internal_functions_filtert>(message_handler));
204
184
205
- goal_filterst goal_filters;
206
185
goal_filters.add (util_make_unique<internal_goals_filtert>(message_handler));
207
186
208
- cover_instrumenterst instrumenters;
209
-
210
187
optionst::value_listt criteria_strings = options.get_list_option (" cover" );
211
- bool keep_assertions=false ;
212
188
189
+ config->keep_assertions = false ;
213
190
for (const auto &criterion_string : criteria_strings)
214
191
{
215
192
try
216
193
{
217
194
coverage_criteriont c = parse_coverage_criterion (criterion_string);
218
195
219
196
if (c == coverage_criteriont::ASSERTION)
220
- keep_assertions = true ;
197
+ config-> keep_assertions = true ;
221
198
222
199
instrumenters.add_from_criterion (c, symbol_table, goal_filters);
223
200
}
224
201
catch (const std::string &e)
225
202
{
226
203
msg.error () << e << messaget::eom;
227
- return true ;
204
+ return {} ;
228
205
}
229
206
}
230
207
231
- if (keep_assertions && criteria_strings.size ()>1 )
208
+ if (config-> keep_assertions && criteria_strings.size ()>1 )
232
209
{
233
210
msg.error () << " assertion coverage cannot currently be used together with "
234
211
<< " 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 {};
253
213
}
254
214
255
215
// cover entry point function only
@@ -266,32 +226,108 @@ bool instrument_cover_goals(
266
226
function_filters.add (
267
227
util_make_unique<trivial_functions_filtert>(message_handler));
268
228
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" );
273
231
274
- function_filters. report_anomalies () ;
275
- goal_filters. report_anomalies ();
232
+ return config ;
233
+ }
276
234
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 )
278
247
{
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 )
285
249
{
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;
289
252
}
253
+ }
254
+
255
+ bool changed = false ;
290
256
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 ;
292
319
}
293
320
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
+
295
331
return false ;
296
332
}
297
333
0 commit comments