Skip to content

Commit 0b099d0

Browse files
committed
goto_check_c: observe check pragmas annotated to individual expressions
This is required to make the conversion of __builtin_X_overflow not generate spurious conversion checks. Fixes: #6452
1 parent fd132cb commit 0b099d0

File tree

6 files changed

+85
-1
lines changed

6 files changed

+85
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef __GNUC__
2+
_Bool __builtin_add_overflow();
3+
#endif
4+
5+
int main()
6+
{
7+
unsigned a, b, c;
8+
if(__builtin_add_overflow(a, b, &c))
9+
return 0;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
conversion-check.c
3+
--conversion-check --unsigned-overflow-check --signed-overflow-check
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^Generated [1-9]\d* VCC\(s\)
9+
--
10+
Zero VCCs should be generated.
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <assert.h>
2+
3+
int nondet_int();
4+
5+
void main()
6+
{
7+
int a = nondet_int();
8+
int b = nondet_int();
9+
int c = a +
10+
#pragma CPROVER check disable "signed-overflow"
11+
(a + b);
12+
#pragma CPROVER check pop
13+
14+
#pragma CPROVER check disable "signed-overflow"
15+
for(int i = 0; i < 10; ++i)
16+
{
17+
int temp = a + b;
18+
#pragma CPROVER check pop
19+
int foo = temp + a;
20+
assert(foo > 2);
21+
}
22+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CORE
2+
main.c
3+
--signed-overflow-check
4+
^\[main.overflow.1\] line 9 arithmetic overflow on signed \+ in a \+ a \+ b: FAILURE$
5+
^\[main.overflow.2\] line 19 arithmetic overflow on signed \+ in temp \+ a: FAILURE$
6+
^\[main.assertion.1\] line 20 assertion foo > 2: FAILURE$
7+
^\*\* 3 of 3 failed
8+
^VERIFICATION FAILED$
9+
^EXIT=10$
10+
^SIGNAL=0$
11+
--
12+
--
13+
No assertions other than the above three are expected.

src/analyses/goto_check_c.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,33 @@ void goto_check_ct::check_rec_arithmetic_op(
18721872

18731873
void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
18741874
{
1875+
flag_resett resetter(expr.source_location());
1876+
const auto &pragmas = expr.source_location().get_pragmas();
1877+
for(const auto &d : pragmas)
1878+
{
1879+
// match named-check related pragmas
1880+
auto matched = match_named_check(d.first);
1881+
if(matched.has_value())
1882+
{
1883+
auto named_check = matched.value();
1884+
auto name = named_check.first;
1885+
auto status = named_check.second;
1886+
bool *flag = name_to_flag.find(name)->second;
1887+
switch(status)
1888+
{
1889+
case check_statust::ENABLE:
1890+
resetter.set_flag(*flag, true, name);
1891+
break;
1892+
case check_statust::DISABLE:
1893+
resetter.set_flag(*flag, false, name);
1894+
break;
1895+
case check_statust::CHECKED:
1896+
resetter.disable_flag(*flag, name);
1897+
break;
1898+
}
1899+
}
1900+
}
1901+
18751902
if(expr.id() == ID_exists || expr.id() == ID_forall)
18761903
{
18771904
// the scoped variables may be used in the assertion

src/goto-programs/goto_convert_side_effect.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -656,9 +656,11 @@ void goto_convertt::remove_overflow(
656656
if(result.type().id() == ID_pointer)
657657
{
658658
result_type = to_pointer_type(result.type()).base_type();
659+
source_locationt source_location_annotated = expr.source_location();
660+
source_location_annotated.add_pragma("disable:conversion-check");
659661
code_assignt result_assignment{dereference_exprt{result},
660662
typecast_exprt{operation, *result_type},
661-
expr.source_location()};
663+
source_location_annotated};
662664
convert_assign(result_assignment, dest, mode);
663665
}
664666
else

0 commit comments

Comments
 (0)