Skip to content

Commit 152719f

Browse files
Merge pull request #5509 from piotr-grabalski/pg-wip-githubissue-5507
Add additional documentation of --nan-check flag
2 parents 94fb414 + 32bee1d commit 152719f

File tree

3 files changed

+116
-0
lines changed

3 files changed

+116
-0
lines changed

doc/cprover-manual/properties.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,21 @@ unsigned foo(unsigned x)
147147
x = x + 2; // unsigned overflow checks are generated here
148148
```
149149
150+
#### Flag --nan-check limitations
151+
152+
Please note that `--nan-check` flag is adding not-a-number checks only for
153+
generation of NaN value. Current implementation of `--nan-check` flag is not
154+
providing checks for propagation of NaN values. Generating assertions on type
155+
casting or structure/union member access is unsupported and such operation
156+
will not be examined.
157+
158+
For example:
159+
160+
```
161+
float f = 0.0/0.0; // will generate NaN - CBMC will add assertion
162+
float g = NAN+0.0; // propagation of NaN value - no assertion generated
163+
```
164+
150165
#### Generating function bodies
151166
152167
Sometimes implementations for called functions are not available in the goto
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <assert.h>
2+
#include <math.h>
3+
#include <stdint.h>
4+
5+
// This test contains a set of operations performed on a floating point numbers
6+
// to verify --nan-check flag. The result of test may change when/if support
7+
// of NaN value propagation checking is supported. Current behaviour of
8+
// --nan-check flag is that it checks whether an arithmetic operation performed
9+
// on a floating point value(s) is generating new not-a-number value. If NaN is
10+
// generated because one of the values is already NaN the assertion is not
11+
// produced.
12+
13+
union container {
14+
uint32_t u;
15+
float f;
16+
};
17+
18+
int main(void)
19+
{
20+
// set special values
21+
float mynan;
22+
__CPROVER_assume(isnan(mynan));
23+
float myinf;
24+
__CPROVER_assume(isinf(myinf) && myinf > 0.0);
25+
float myzero;
26+
__CPROVER_assume(myzero == 0.0f);
27+
28+
// variables
29+
union container c = {UINT32_MAX};
30+
int n;
31+
32+
// should generate assertion if --nan-check flag will support
33+
// NaN propagation checking
34+
float g = (float)(c.u);
35+
float f = c.f;
36+
f = c.f + myzero;
37+
38+
// these operations should generate assertions
39+
// 0.0 / 0.0 = NaN
40+
f = myzero / myzero;
41+
// n / Inf = NaN
42+
f = n / (myinf);
43+
// Inf * 0 = NaN
44+
f = (myinf)*myzero;
45+
// -Inf + Inf = NaN
46+
f = (-myinf) + (myinf);
47+
// Inf + (-Inf) = NaN
48+
f = (myinf) + (-myinf);
49+
// Inf - Inf = NaN
50+
f = (myinf) - (myinf);
51+
// -Inf - (-Inf) = NaN
52+
f = (-myinf) - (-myinf);
53+
54+
// NaN + NaN = NaN
55+
f = c.f + c.f;
56+
// NaN / 0.0 = NaN
57+
f = c.f / myzero;
58+
// NaN * NaN = NaN
59+
f = mynan * mynan;
60+
// NaN + NaN = NaN
61+
f = mynan + mynan;
62+
// NaN - NaN = NaN
63+
f = mynan - mynan;
64+
// NaN / NaN = NaN
65+
f = mynan / mynan;
66+
// NAN + n = NaN
67+
f = mynan + n;
68+
// NAN - n = NaN
69+
f = mynan - n;
70+
// NAN * n = NaN
71+
f = mynan * n;
72+
// NAN / n = NaN
73+
f = mynan / n;
74+
75+
return 0;
76+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
CORE
2+
main.c
3+
--nan-check
4+
\[main.NaN.1\] line \d+ NaN on \+ in byte_extract_little_endian\(c, (0|0l|0ll), float\) \+ myzero: SUCCESS
5+
\[main.NaN.2\] line \d+ NaN on / in myzero / myzero: FAILURE
6+
\[main.NaN.3\] line \d+ NaN on / in \(float\)n / myinf: FAILURE
7+
\[main.NaN.4\] line \d+ NaN on \* in myinf \* myzero: FAILURE
8+
\[main.NaN.5\] line \d+ NaN on \+ in -myinf \+ myinf: FAILURE
9+
\[main.NaN.6\] line \d+ NaN on - in myinf - myinf: FAILURE
10+
\[main.NaN.7\] line \d+ NaN on - in -myinf - -myinf: FAILURE
11+
\[main.NaN.8\] line \d+ NaN on \+ in byte_extract_little_endian\(c, (0|0l|0ll), float\) \+ byte_extract_little_endian\(c, (0|0l|0ll), float\): SUCCESS
12+
\[main.NaN.9\] line \d+ NaN on / in byte_extract_little_endian\(c, (0|0l|0ll), float\) / myzero: SUCCESS
13+
\[main.NaN.10\] line \d+ NaN on \* in mynan \* mynan: SUCCESS
14+
\[main.NaN.11\] line \d+ NaN on \+ in mynan \+ mynan: SUCCESS
15+
\[main.NaN.12\] line \d+ NaN on - in mynan - mynan: SUCCESS
16+
\[main.NaN.13\] line \d+ NaN on / in mynan / mynan: SUCCESS
17+
\[main.NaN.14\] line \d+ NaN on \+ in mynan \+ \(float\)n: SUCCESS
18+
\[main.NaN.15\] line \d+ NaN on - in mynan - \(float\)n: SUCCESS
19+
\[main.NaN.16\] line \d+ NaN on \* in mynan \* \(float\)n: SUCCESS
20+
\[main.NaN.17\] line \d+ NaN on / in mynan / \(float\)n: SUCCESS
21+
^EXIT=10$
22+
^SIGNAL=0$
23+
^VERIFICATION FAILED$
24+
--
25+
\[main.NaN.18\]

0 commit comments

Comments
 (0)