@@ -64,6 +64,18 @@ class basic_blockst
64
64
}
65
65
};
66
66
67
+ /* ******************************************************************\
68
+
69
+ Function: as_string
70
+
71
+ Inputs:
72
+
73
+ Outputs:
74
+
75
+ Purpose:
76
+
77
+ \*******************************************************************/
78
+
67
79
const char *as_string (coverage_criteriont c)
68
80
{
69
81
switch (c)
@@ -82,6 +94,30 @@ const char *as_string(coverage_criteriont c)
82
94
83
95
/* ******************************************************************\
84
96
97
+ Function: is_condition
98
+
99
+ Inputs:
100
+
101
+ Outputs:
102
+
103
+ Purpose:
104
+
105
+ \*******************************************************************/
106
+
107
+ bool is_condition (const exprt &src)
108
+ {
109
+ if (src.type ().id ()!=ID_bool) return false ;
110
+
111
+ // conditions are 'atomic predicates'
112
+ if (src.id ()==ID_and || src.id ()==ID_or ||
113
+ src.id ()==ID_not || src.id ()==ID_implies)
114
+ return false ;
115
+
116
+ return true ;
117
+ }
118
+
119
+ /* ******************************************************************\
120
+
85
121
Function: collect_conditions_rec
86
122
87
123
Inputs:
@@ -102,22 +138,8 @@ void collect_conditions_rec(const exprt &src, std::set<exprt> &dest)
102
138
for (const auto & op : src.operands ())
103
139
collect_conditions_rec (op, dest);
104
140
105
- if (src.type ().id ()==ID_bool)
106
- {
107
- if (src.id ()==ID_and || src.id ()==ID_or ||
108
- src.id ()==ID_not || src.id ()==ID_implies)
109
- {
110
- // ignore me
111
- }
112
- else if (src.is_constant ())
113
- {
114
- // ignore me
115
- }
116
- else
117
- {
118
- dest.insert (src);
119
- }
120
- }
141
+ if (is_condition (src) && !src.is_constant ())
142
+ dest.insert (src);
121
143
}
122
144
123
145
/* ******************************************************************\
@@ -171,6 +193,29 @@ std::set<exprt> collect_conditions(const goto_programt::const_targett t)
171
193
172
194
/* ******************************************************************\
173
195
196
+ Function: collect_operands
197
+
198
+ Inputs:
199
+
200
+ Outputs:
201
+
202
+ Purpose:
203
+
204
+ \*******************************************************************/
205
+
206
+ void collect_operands (const exprt &src, std::vector<exprt> &dest)
207
+ {
208
+ for (const exprt &op : src.operands ())
209
+ {
210
+ if (op.id ()==src.id ())
211
+ collect_operands (op, dest);
212
+ else
213
+ dest.push_back (op);
214
+ }
215
+ }
216
+
217
+ /* ******************************************************************\
218
+
174
219
Function: collect_mcdc_controlling_rec
175
220
176
221
Inputs:
@@ -183,29 +228,67 @@ Function: collect_mcdc_controlling_rec
183
228
184
229
void collect_mcdc_controlling_rec (
185
230
const exprt &src,
231
+ const std::vector<exprt> &conditions,
186
232
std::set<exprt> &result)
187
233
{
188
- if (src.id ()==ID_and)
234
+ if (src.id ()==ID_and ||
235
+ src.id ()==ID_or)
189
236
{
190
- if (src.operands ().size ()==2 )
191
- {
192
- exprt cond1=
193
- conjunction ({ src.op0 (), not_exprt (src.op1 ()) });
237
+ std::vector<exprt> operands;
238
+ collect_operands (src, operands);
194
239
195
- exprt cond2=
196
- conjunction ({ not_exprt (src.op0 ()), src.op1 () });
240
+ if (operands.size ()==1 )
241
+ {
242
+ exprt e=*operands.begin ();
243
+ collect_mcdc_controlling_rec (e, conditions, result);
244
+ }
245
+ else if (!operands.empty ())
246
+ {
247
+ for (unsigned i=0 ; i<operands.size (); i++)
248
+ {
249
+ const exprt op=operands[i];
250
+
251
+ if (is_condition (op))
252
+ {
253
+ std::vector<exprt> o=operands;
197
254
198
- result.insert (cond1);
199
- result.insert (cond2);
255
+ // 'o[i]' needs to be true and false
256
+ std::vector<exprt> new_conditions=conditions;
257
+ new_conditions.push_back (conjunction (o));
258
+ result.insert (conjunction (new_conditions));
259
+
260
+ o[i].make_not ();
261
+ new_conditions.back ()=conjunction (o);
262
+ result.insert (conjunction (new_conditions));
263
+ }
264
+ else
265
+ {
266
+ std::vector<exprt> others;
267
+ others.reserve (operands.size ()-1 );
268
+
269
+ for (unsigned j=0 ; j<operands.size (); j++)
270
+ if (i!=j)
271
+ {
272
+ if (src.id ()==ID_or)
273
+ others.push_back (not_exprt (operands[j]));
274
+ else
275
+ others.push_back (operands[j]);
276
+ }
277
+
278
+ exprt c=conjunction (others);
279
+ std::vector<exprt> new_conditions=conditions;
280
+ new_conditions.push_back (c);
281
+
282
+ collect_mcdc_controlling_rec (op, new_conditions, result);
283
+ }
284
+ }
200
285
}
201
- else
202
- collect_mcdc_controlling_rec (make_binary (src), result);
203
286
}
204
- else if (src.id ()==ID_or )
287
+ else if (src.id ()==ID_not )
205
288
{
289
+ exprt e=to_not_expr (src).op ();
290
+ collect_mcdc_controlling_rec (e, conditions, result);
206
291
}
207
- else if (src.id ()==ID_not)
208
- collect_mcdc_controlling_rec (to_not_expr (src).op (), result);
209
292
}
210
293
211
294
/* ******************************************************************\
@@ -226,7 +309,7 @@ std::set<exprt> collect_mcdc_controlling(
226
309
std::set<exprt> result;
227
310
228
311
for (const auto &d : decisions)
229
- collect_mcdc_controlling_rec (d, result);
312
+ collect_mcdc_controlling_rec (d, { }, result);
230
313
231
314
return result;
232
315
}
0 commit comments