1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
|
/* { dg-options "-fcondition-coverage -ftest-coverage -O2" } */
/* { dg-do compile } */
#include <stdint.h>
#include <limits.h>
#include <setjmp.h>
jmp_buf buf;
int id (int);
int idp (int *);
int err;
char c;
/* This becomes problematic only under optimization for the case when the
compiler cannot inline the function but have to generate a call. It is not
really interesting to run, only build. Notably, both the function calls and
the return values are important to construct a problematic graph.
This test is also a good example of where optimization makes condition
coverage unpredictable, but not unusable. If this is built without
optimization the conditions work as you would expect from reading the
source. */
/* Adapted from cpio-2.14 gnu/utmens.c lutimens (). */
int
mcdc001 (int *v)
{
int adjusted;
int adjustment_needed = 0;
int *ts = v ? &adjusted : 0; /* conditions(0/4) true(0 1) false(0 1) */
/* conditions(end) */
if (ts)
adjustment_needed = idp (ts);
if (adjustment_needed < 0)
return -1;
if (adjustment_needed) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
{
if (adjustment_needed != 3) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
return -1;
if (ts) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
return 0;
}
if (adjustment_needed && idp (&adjusted)) /* conditions(0/4) true(0 1) false(0 1) */
/* conditions(end) */
return -1;
if (adjusted) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
return idp (ts);
return -1;
}
/* This failed when the candidate set internal/contracted-past nodes were not
properly marked as reachable in the candidate reduction phase. */
/* Adapted from cpio-2.14 gnu/mktime.c mktime_internal (). */
int
mcdc002 ()
{
int a;
if (idp (&a)) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
{
if (id (a)) /* conditions(0/2) true(0/2) true(0) false(0) */
/* conditions(end) */
goto exit;
if (err) /* conditions(0/2) true(0/2) true(0) false(0) */
/* conditions(end) */
return -1;
}
exit:
return a;
}
/* Adapted from icu4c-73.1 common/ucase.cpp ucase_getCaseLocale (). */
int
mcdc003 (const char *locale)
{
/* extern, so its effect won't be optimized out. */
c = *locale++;
if (c == 'z') /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
{
return 1;
}
else if (c >= 'a') /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
{
if (id (c)) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
c = *locale++;
}
else
{
if (c == 'T')
{
if (id (c)) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
c = *locale++;
if (id (c)) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
c = *locale++;
}
/* This may or may not become a jump table. */
else if (c == 'L') /* conditions(suppress) */
/* conditions(end) */
c = *locale++;
else if (c == 'E') /* conditions(suppress) */
/* conditions(end) */
c = *locale++;
else if (c == 'N') /* conditions(suppress) */
/* conditions(end) */
c = *locale++;
else if (c == 'H') /* conditions(suppress) */
/* conditions(end) */
{
c = *locale++;
if (id (c)) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
c = *locale++;
}
}
return 1;
}
/* The || will be changed to |, so it is impractical to predict the number of
conditions. If the walk is not properly implemented this will not finish
compiling, so the actual coverage is not interesting. */
/* Adapted from icu4c-73.1 common/uresdata.cpp res_findResource (). */
int
mcdc004 (int r, char* path, char* key)
{
char *idcc (char *, char);
#define is_kind1(type) ((type) == 23 || (type) == 14 || (type == 115))
#define is_kind2(type) ((type) == 16 || (type) == 77 || (type == 118))
#define is_kind12(type) (is_kind1 ((type)) || is_kind2 ((type)))
char *nextSepP = path;
int t1 = r;
int type = id (t1);
if (!is_kind12 (type)) /* conditions(suppress) */
/* conditions(end) */
return -1;
while (*path && t1 != -1 && is_kind12 (type)) /* conditions(suppress) */
/* conditions(end) */
{
nextSepP = idcc(path, '/');
if(nextSepP == path) /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
return -1;
if (*nextSepP == 'a') /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
*key = *path;
else if (*nextSepP == 'b') /* conditions(0/2) true(0) false(0) */
/* conditions(end) */
*key = 0;
type = t1;
}
return t1;
}
/* Adapted from jxl 0.8.2 lib/extras/dec/apng.cc processing_start ().
This created a graph where depth-first traversal of the CFG would not
process nodes in the wrong order (the extra control inserted from setjmp
created a path of complexes from root to !b without going through !a).
This only happened under optimization. */
int
mcdc005 (int a, int b)
{
a = id (a);
b = id (b);
/* The a || b gets transformed to a | b, then fused with setjmp because
they both have the same return value. */
if (a || b) /* conditions(0/4) true(0 1) false(0 1) */
/* conditions(end) */
return 1;
else
a += 1;
if (setjmp (buf))
return 1;
return a;
}
/* Adapted from cpio-2.14 gnu/quotearg.c quotearg_buffer_restyled. The ifs in
the cases (with fallthrough) re-use the same value which under optimization
causes path reuse which must be sorted out. */
int
mcdc006 (int quoting_style, int elide, int *buffer)
{
int backslash = 0;
switch (quoting_style)
{
case 1:
if (!elide)
backslash = 1;
case 2:
if (!elide)
if (buffer)
*buffer = '"';
}
if (quoting_style == 2 && backslash)
quoting_style = 1;
return 1;
}
/* Adapted from pcre2-10.42 pcre2_compile.c pcre2_compile. If SSA nodes are
created at the wrong place in the block it will fail flow analysis (because
the label is in the middle of block), caused by the final break in this
case. */
void
mcdc007 (int options, int *pso, int len)
{
if (options == 5)
return;
while (options--)
{
int i;
for (i = 0; i < len; i++)
{
int *p = pso + i;
int skipatstart = *p + 2;
if (skipatstart) {
switch(*p)
{
case 1:
*p |= *p + 1;
break;
case 2:
skipatstart += *p - skipatstart;
break;
}
break;
}
}
if (i >= len) break;
}
}
/* Adapted from alsa-lib 1.2.8 pcm/pcm.c snd_pcm_chmap_print. */
int
mcdc008 (int *map, unsigned maxlen, int *buf)
{
unsigned int len = 0;
for (unsigned i = 0; i < *map; i++) {
unsigned int p = map[i] & 0xF;
if (i > 0) {
if (len >= maxlen)
return -1;
}
if (map[i] & 0xFF)
len += idp (buf + len);
else {
len += idp (buf);
}
if (map[i] & 0xFF00) {
len += idp (buf + len);
if (len >= maxlen)
return -1;
}
}
return len;
}
/* Adapted from cpio-2.14 gnu/mktime.c mktime_internal (). The combination of
goto, automatic variables, and the ternary causes the post dominator of the
highest topological ordered node not to be the common post dominator of the
expression as a whole. */
int
mcdc009 (int *tp, int t, int isdst)
{
int t0 = tp[0];
int t1 = tp[1];
int t2 = tp[2];
if (t0 < 0 || (isdst < 0 ? t1 : (isdst != 0)))
goto offset_found;
if (t == 0)
return -1;
t1 = t2;
offset_found:
return t;
}
/* Adapted from Berkeley db 4.8.30 rep/rep_elect.c __rep_cmp_vote. This
particular combination of fallthrough and folding creates a path into the
the inner if () that does not go through the first basic condition. */
void
mcdc010 (int cmp, int *rep, int sites, int priority, int flags)
{
if (sites > 1 && (priority != 0 || (flags & 0xFF)))
{
if ( (priority != 0 && *rep == 0)
|| (((priority == 0 && *rep == 0)
|| (priority != 0 && *rep != 0)) && cmp > 0))
{
*rep = cmp;
}
}
}
/* For not sufficiently protected back edges this would create an infinite
loop. */
void
mcdc011 (int a, int b)
{
if (a && id (b))
for (;;) {}
id (a+1);
}
/* Adapted from alsa-1.2.8 tlv.c get_tlv_info (). Under optimization, the
conditions may be replaced with min (). */
int
mcdc012 (int x, int y)
{
int err;
err = id (x);
if (err < 0)
return err;
err = id (y);
if (err < 0)
return err;
return 0;
}
/* Adapted from alsa-1.2.8 control.c snd_ctl_elem_id_compare_numid (). This
test is probably not so accurate on targets where int == int64. Under
optimization, the conditions may be replaced with min/max. */
int
mcdc013 (const int64_t *id1, const int64_t *id2)
{
int64_t d;
d = *id1 - *id2;
if (d & 0xFF)
{
if (d > INT_MAX)
d = INT_MAX;
else if (d < INT_MIN)
d = INT_MIN;
}
return d;
}
|