Skip to content

Commit bfad11a

Browse files
authored
Merge pull request #5808 from TGWDB/CPROVER-enum-is-in-range
This adds a new builtin function __CPROVER_enum_is_in_range to determine if an enum is one of the valid enum values. This fixes issue 5473: #5473
2 parents 27072c6 + baab734 commit bfad11a

19 files changed

+371
-0
lines changed

doc/cprover-manual/api.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,38 @@ stored in the given arrays are equal. The function
125125
the array **dest**. The function **\_\_CPROVER\_array\_set** initializes
126126
the array **dest** with the given value.
127127
128+
129+
#### \_\_CPROVER\_enum\_is\_in\_range
130+
131+
```C
132+
__CPROVER_bool __CPROVER_enum_is_in_range();
133+
```
134+
135+
The function **\_\_CPROVER\_enum\_is\_in\_range** is used to check
136+
that an enumeration has one of the defined enumeration values. In
137+
the following example `__CPROVER_enum_is_in_range(ev1)` will return
138+
true and the assertion will pass
139+
```C
140+
enum my_enum { first, second };
141+
142+
int main()
143+
{
144+
enum my_enum ev1 = second;
145+
assert(__CPROVER_enum_is_in_range(ev1));
146+
}
147+
```
148+
However, in the example below the assertion will fail
149+
```C
150+
enum my_enum { first, second };
151+
152+
int main()
153+
{
154+
enum my_enum ev1 = second + 1;
155+
assert(__CPROVER_enum_is_in_range(ev1));
156+
}
157+
```
158+
159+
128160
#### Uninterpreted Functions
129161

130162
Uninterpreted functions are documented [here](./modeling-nondeterminism.md)).
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
3+
enum my_enum
4+
{
5+
first,
6+
second,
7+
third,
8+
fourth,
9+
fifth
10+
};
11+
12+
int main()
13+
{
14+
enum my_enum ev1;
15+
enum my_enum ev2;
16+
ev1 = first;
17+
ev2 = fifth;
18+
int i = 0;
19+
while(i < 10)
20+
{
21+
ev1++;
22+
assert(__CPROVER_enum_is_in_range(i));
23+
i++;
24+
}
25+
return 0;
26+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
enum_test10.c
3+
4+
^EXIT=(6|70)$
5+
^SIGNAL=0$
6+
^file enum_test10.c line \d+ function main: __CPROVER_enum_is_in_range expects enum, but \(i\) has type `signed int`$
7+
--
8+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(i\): SUCCESS$
9+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(i\): FAILURE$
10+
^\*\*\*\* WARNING: no body for function __CPROVER_enum_is_in_range$
11+
--
12+
This test the type checking of argument for __CPROVER_enum_is_in_range
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <assert.h>
2+
3+
enum my_enum
4+
{
5+
first,
6+
second,
7+
third,
8+
fourth,
9+
fifth
10+
};
11+
12+
int main()
13+
{
14+
enum my_enum ev1;
15+
enum my_enum ev2;
16+
ev1 = first;
17+
ev2 = fifth;
18+
assert(__CPROVER_enum_is_in_range(ev1, ev2));
19+
return 0;
20+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
enum_test12.c
3+
4+
^EXIT=(6|70)$
5+
^SIGNAL=0$
6+
^file enum_test12.c line \d+ function main: __CPROVER_enum_is_in_range takes exactly 1 argument, but 2 were provided$
7+
--
8+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(.*\): SUCCESS$
9+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(.*\): FAILURE$
10+
^\*\*\*\* WARNING: no body for function __CPROVER_enum_is_in_range$
11+
--
12+
This test the type checking of argument for __CPROVER_enum_is_in_range
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <assert.h>
2+
3+
enum my_enum
4+
{
5+
first,
6+
second,
7+
third,
8+
fourth,
9+
fifth
10+
};
11+
12+
int main()
13+
{
14+
enum my_enum ev1;
15+
enum my_enum ev2;
16+
ev1 = first;
17+
ev2 = fifth;
18+
while(ev1 != ev2)
19+
{
20+
ev1++;
21+
assert(__CPROVER_enum_is_in_range(ev1));
22+
}
23+
return 0;
24+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
enum_test3.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(ev1\): SUCCESS
7+
--
8+
^\*\*\*\* WARNING: no body for function __CPROVER_enum_is_in_range
9+
--
10+
This test is for the enum_is_in_range working properly, the negation
11+
is if the function is not defined.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
3+
enum my_enum
4+
{
5+
first,
6+
second,
7+
third,
8+
fourth,
9+
fifth
10+
};
11+
12+
int main()
13+
{
14+
enum my_enum ev1;
15+
enum my_enum ev2;
16+
ev1 = first;
17+
ev2 = fifth;
18+
int i = 0;
19+
while(i < 10)
20+
{
21+
ev1++;
22+
assert(__CPROVER_enum_is_in_range(ev1));
23+
i++;
24+
}
25+
return 0;
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
enum_test4.c
3+
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(ev1\): FAILURE$
7+
--
8+
^\[main.assertion.1\] line \d+ assertion __CPROVER_enum_is_in_range\(ev1\): SUCCESS$
9+
^\*\*\*\* WARNING: no body for function __CPROVER_enum_is_in_range$
10+
--
11+
This test is for the enum_is_in_range working properly and detecting
12+
when the enum is not in range. The negation tests are to ensure the
13+
out of range is detected, and if the function is not defined.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <assert.h>
2+
3+
enum my_enum
4+
{
5+
first,
6+
second,
7+
third,
8+
fourth,
9+
fifth
10+
};
11+
12+
void testfun(enum my_enum ee)
13+
{
14+
}
15+
16+
int main()
17+
{
18+
enum my_enum ev1;
19+
enum my_enum ev2;
20+
__CPROVER_assume(__CPROVER_enum_is_in_range(ev1));
21+
enum my_enum ev3 = ev1;
22+
testfun(ev3);
23+
testfun(ev2);
24+
return 0;
25+
}

0 commit comments

Comments
 (0)