Skip to content

Commit 577cfee

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 a761762 commit 577cfee

File tree

6 files changed

+88
-3
lines changed

6 files changed

+88
-3
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
@@ -1896,6 +1896,33 @@ void goto_check_ct::check_rec_arithmetic_op(
18961896

18971897
void goto_check_ct::check_rec(const exprt &expr, const guardt &guard)
18981898
{
1899+
flag_overridet resetter(expr.source_location());
1900+
const auto &pragmas = expr.source_location().get_pragmas();
1901+
for(const auto &d : pragmas)
1902+
{
1903+
// match named-check related pragmas
1904+
auto matched = match_named_check(d.first);
1905+
if(matched.has_value())
1906+
{
1907+
auto named_check = matched.value();
1908+
auto name = named_check.first;
1909+
auto status = named_check.second;
1910+
bool *flag = name_to_flag.find(name)->second;
1911+
switch(status)
1912+
{
1913+
case check_statust::ENABLE:
1914+
resetter.set_flag(*flag, true, name);
1915+
break;
1916+
case check_statust::DISABLE:
1917+
resetter.set_flag(*flag, false, name);
1918+
break;
1919+
case check_statust::CHECKED:
1920+
resetter.disable_flag(*flag, name);
1921+
break;
1922+
}
1923+
}
1924+
}
1925+
18991926
if(expr.id() == ID_exists || expr.id() == ID_forall)
19001927
{
19011928
// the scoped variables may be used in the assertion

src/goto-programs/goto_convert_side_effect.cpp

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

0 commit comments

Comments
 (0)