@@ -79,6 +79,65 @@ const char *as_string(coverage_criteriont c)
79
79
80
80
/* ******************************************************************\
81
81
82
+ Function: collect_conditions_rec
83
+
84
+ Inputs:
85
+
86
+ Outputs:
87
+
88
+ Purpose:
89
+
90
+ \*******************************************************************/
91
+
92
+ void collect_conditions_rec (const exprt &src, std::set<exprt> &dest)
93
+ {
94
+ if (src.id ()==ID_address_of)
95
+ {
96
+ return ;
97
+ }
98
+
99
+ for (const auto & op : src.operands ())
100
+ collect_conditions_rec (op, dest);
101
+
102
+ if (src.type ().id ()==ID_bool)
103
+ {
104
+ if (src.id ()==ID_and || src.id ()==ID_or ||
105
+ src.id ()==ID_not || src.id ()==ID_implies)
106
+ {
107
+ // ignore me
108
+ }
109
+ else if (src.is_constant ())
110
+ {
111
+ // ignore me
112
+ }
113
+ else
114
+ {
115
+ dest.insert (src);
116
+ }
117
+ }
118
+ }
119
+
120
+ /* ******************************************************************\
121
+
122
+ Function: collect_conditions
123
+
124
+ Inputs:
125
+
126
+ Outputs:
127
+
128
+ Purpose:
129
+
130
+ \*******************************************************************/
131
+
132
+ std::set<exprt> collect_conditions (const exprt &src)
133
+ {
134
+ std::set<exprt> result;
135
+ collect_conditions_rec (src, result);
136
+ return result;
137
+ }
138
+
139
+ /* ******************************************************************\
140
+
82
141
Function: collect_conditions
83
142
84
143
Inputs:
@@ -89,21 +148,114 @@ Function: collect_conditions
89
148
90
149
\*******************************************************************/
91
150
92
- void collect_conditions ( const exprt &src, std::set<exprt> &dest )
151
+ std::set<exprt> collect_conditions ( const goto_programt::const_targett t )
93
152
{
94
- if (src.id ()==ID_and || src.id ()==ID_or ||
95
- src.id ()==ID_not || src.id ()==ID_implies)
153
+ switch (t->type )
96
154
{
97
- forall_operands (it, src)
98
- collect_conditions (*it, dest);
155
+ case GOTO:
156
+ case ASSUME:
157
+ case ASSERT:
158
+ return collect_conditions (t->guard );
159
+
160
+ case ASSIGN:
161
+ case FUNCTION_CALL:
162
+ return collect_conditions (t->code );
163
+
164
+ default :;
99
165
}
100
- else if (src.is_true ())
166
+
167
+ return std::set<exprt>();
168
+ }
169
+
170
+ /* ******************************************************************\
171
+
172
+ Function: collect_decisions_rec
173
+
174
+ Inputs:
175
+
176
+ Outputs:
177
+
178
+ Purpose:
179
+
180
+ \*******************************************************************/
181
+
182
+ void collect_decisions_rec (const exprt &src, std::set<exprt> &dest)
183
+ {
184
+ if (src.id ()==ID_address_of)
101
185
{
186
+ return ;
187
+ }
188
+
189
+ if (src.type ().id ()==ID_bool)
190
+ {
191
+ if (src.is_constant ())
192
+ {
193
+ // ignore me
194
+ }
195
+ else if (src.id ()==ID_not)
196
+ {
197
+ collect_decisions_rec (src.op0 (), dest);
198
+ }
199
+ else
200
+ {
201
+ dest.insert (src);
202
+ }
102
203
}
103
204
else
104
205
{
105
- dest.insert (src);
206
+ for (const auto & op : src.operands ())
207
+ collect_decisions_rec (op, dest);
208
+ }
209
+ }
210
+
211
+ /* ******************************************************************\
212
+
213
+ Function: collect_decisions
214
+
215
+ Inputs:
216
+
217
+ Outputs:
218
+
219
+ Purpose:
220
+
221
+ \*******************************************************************/
222
+
223
+ std::set<exprt> collect_decisions (const exprt &src)
224
+ {
225
+ std::set<exprt> result;
226
+ collect_decisions_rec (src, result);
227
+ return result;
228
+ }
229
+
230
+ /* ******************************************************************\
231
+
232
+ Function: collect_decisions
233
+
234
+ Inputs:
235
+
236
+ Outputs:
237
+
238
+ Purpose:
239
+
240
+ \*******************************************************************/
241
+
242
+ std::set<exprt> collect_decisions (const goto_programt::const_targett t)
243
+ {
244
+ switch (t->type )
245
+ {
246
+ case GOTO:
247
+ case ASSUME:
248
+ case ASSERT:
249
+ return collect_decisions (t->guard );
250
+
251
+ case ASSIGN:
252
+ case FUNCTION_CALL:
253
+ return collect_decisions (t->code );
254
+
255
+ default :;
106
256
}
257
+
258
+ return std::set<exprt>();
107
259
}
108
260
109
261
/* ******************************************************************\
@@ -190,32 +342,73 @@ void instrument_cover_goals(
190
342
break ;
191
343
192
344
case coverage_criteriont::CONDITION:
193
- if (i_it-> is_goto ())
345
+ // Conditions are all atomic predicates in the programs.
194
346
{
195
- std::set<exprt> conditions;
347
+ std::set<exprt> conditions=
348
+ collect_conditions (i_it);
349
+
350
+ source_locationt source_location=i_it->source_location ;
196
351
197
- collect_conditions (i_it->guard , conditions);
198
- unsigned i=0 ;
352
+ for (const auto & c : conditions)
353
+ {
354
+ std::string comment_t =" condition " +from_expr (ns, " " , c)+" true" ;
355
+ goto_program.insert_before_swap (i_it);
356
+ i_it->make_assertion (c);
357
+ i_it->source_location =source_location;
358
+ i_it->source_location .set_comment (comment_t );
359
+
360
+ std::string comment_f=" condition " +from_expr (ns, " " , c)+" false" ;
361
+ goto_program.insert_before_swap (i_it);
362
+ i_it->make_assertion (not_exprt (c));
363
+ i_it->source_location =source_location;
364
+ i_it->source_location .set_comment (comment_f);
365
+ }
366
+
367
+ for (unsigned i=0 ; i<conditions.size ()*2 ; i++)
368
+ i_it++;
369
+ }
370
+ break ;
371
+
372
+ case coverage_criteriont::DECISION:
373
+ // Decisions are maximal Boolean combinations of conditions.
374
+ {
375
+ std::set<exprt> decisions=
376
+ collect_decisions (i_it);
199
377
200
- exprt guard=i_it->guard ;
201
378
source_locationt source_location=i_it->source_location ;
202
379
203
- for (std::set<exprt>::const_iterator it=conditions.begin ();
204
- it!=conditions.end ();
205
- it++, i++)
380
+ for (const auto & d : decisions)
206
381
{
207
- std::string comment= " condition " +from_expr (ns, " " , *it) ;
382
+ std::string comment_t = " decision " +from_expr (ns, " " , d)+ " true " ;
208
383
goto_program.insert_before_swap (i_it);
209
- i_it->make_assertion (*it );
384
+ i_it->make_assertion (d );
210
385
i_it->source_location =source_location;
211
- i_it->source_location .set_comment (comment);
386
+ i_it->source_location .set_comment (comment_t );
387
+
388
+ std::string comment_f=" decision " +from_expr (ns, " " , d)+" false" ;
389
+ goto_program.insert_before_swap (i_it);
390
+ i_it->make_assertion (not_exprt (d));
391
+ i_it->source_location =source_location;
392
+ i_it->source_location .set_comment (comment_f);
212
393
}
213
394
214
- for (unsigned i=0 ; i<conditions .size (); i++)
395
+ for (unsigned i=0 ; i<decisions .size ()* 2 ; i++)
215
396
i_it++;
216
397
}
217
398
break ;
218
399
400
+
401
+ case coverage_criteriont::MCDC:
402
+ // 1. Each entry and exit point is invoked
403
+ // 2. Each decision takes every possible outcome
404
+ // 3. Each condition in a decision takes every possible outcome
405
+ // 4. Each condition in a decision is shown to independently
406
+ // affect the outcome of the decision.
407
+ break ;
408
+
409
+ case coverage_criteriont::PATH:
410
+ break ;
411
+
219
412
default :;
220
413
}
221
414
}
0 commit comments