Skip to content

Commit 81f1fb6

Browse files
authored
Merge pull request #7560 from tautschnig/bugfixes/r_w_ok-decl
Avoid confusing "__CPROVER_{r,w,rw}_ok is not declared" warning
2 parents 3fe510e + bc174f3 commit 81f1fb6

File tree

7 files changed

+131
-64
lines changed

7 files changed

+131
-64
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int *p = (int *)0;
6+
#ifdef TOO_MANY_ARGS
7+
assert(!__CPROVER_r_ok(p, sizeof(int), 42));
8+
#elif defined(NOT_A_POINTER)
9+
assert(!__CPROVER_r_ok(*p, sizeof(int)));
10+
#elif defined(VOID_POINTER_NO_SIZE)
11+
assert(!__CPROVER_r_ok((void *)p));
12+
#endif
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
-DNOT_A_POINTER
4+
__CPROVER_r_ok expects a pointer as first argument$
5+
^CONVERSION ERROR$
6+
^EXIT=(64|1)$
7+
^SIGNAL=0$
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
-DTOO_MANY_ARGS
4+
__CPROVER_r_ok expects one or two operands$
5+
^CONVERSION ERROR$
6+
^EXIT=(64|1)$
7+
^SIGNAL=0$
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
-DVOID_POINTER_NO_SIZE
4+
__CPROVER_r_ok expects a size when given a void pointer$
5+
^CONVERSION ERROR$
6+
^EXIT=(64|1)$
7+
^SIGNAL=0$

regression/ansi-c/r_w_ok1/main.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
int main()
5+
{
6+
int *p = NULL;
7+
8+
assert(!__CPROVER_r_ok(p, sizeof(int)));
9+
assert(!__CPROVER_w_ok(p, sizeof(int)));
10+
11+
p = malloc(sizeof(int));
12+
13+
assert(__CPROVER_r_ok(p, 1));
14+
assert(__CPROVER_w_ok(p, 1));
15+
assert(__CPROVER_r_ok(p, sizeof(int)));
16+
assert(__CPROVER_w_ok(p, sizeof(int)));
17+
18+
size_t n;
19+
char *arbitrary_size = malloc(n);
20+
21+
assert(__CPROVER_r_ok(arbitrary_size, n));
22+
assert(__CPROVER_w_ok(arbitrary_size, n));
23+
24+
assert(__CPROVER_r_ok(arbitrary_size, n + 1));
25+
assert(__CPROVER_w_ok(arbitrary_size, n + 1));
26+
}

regression/ansi-c/r_w_ok1/test.desc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--verbosity 2
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
function '__CPROVER_[rw]_ok' is not declared

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,6 +2218,70 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
22182218
expr.swap(lowered);
22192219
return;
22202220
}
2221+
else if(
2222+
identifier == CPROVER_PREFIX "r_ok" ||
2223+
identifier == CPROVER_PREFIX "w_ok" ||
2224+
identifier == CPROVER_PREFIX "rw_ok")
2225+
{
2226+
if(expr.arguments().size() != 1 && expr.arguments().size() != 2)
2227+
{
2228+
throw invalid_source_file_exceptiont{
2229+
id2string(identifier) + " expects one or two operands",
2230+
f_op.source_location()};
2231+
}
2232+
2233+
// the first argument must be a pointer
2234+
auto &pointer_expr = expr.arguments()[0];
2235+
if(pointer_expr.type().id() == ID_array)
2236+
{
2237+
auto dest_type = pointer_type(void_type());
2238+
dest_type.base_type().set(ID_C_constant, true);
2239+
implicit_typecast(pointer_expr, dest_type);
2240+
}
2241+
else if(pointer_expr.type().id() != ID_pointer)
2242+
{
2243+
throw invalid_source_file_exceptiont{
2244+
id2string(identifier) + " expects a pointer as first argument",
2245+
f_op.source_location()};
2246+
}
2247+
2248+
// The second argument, when given, is a size_t.
2249+
// When not given, use the pointer subtype.
2250+
exprt size_expr;
2251+
2252+
if(expr.arguments().size() == 2)
2253+
{
2254+
implicit_typecast(expr.arguments()[1], size_type());
2255+
size_expr = expr.arguments()[1];
2256+
}
2257+
else
2258+
{
2259+
// Won't do void *
2260+
const auto &subtype =
2261+
to_pointer_type(pointer_expr.type()).base_type();
2262+
if(subtype.id() == ID_empty)
2263+
{
2264+
throw invalid_source_file_exceptiont{
2265+
id2string(identifier) +
2266+
" expects a size when given a void pointer",
2267+
f_op.source_location()};
2268+
}
2269+
2270+
auto size_expr_opt = size_of_expr(subtype, *this);
2271+
CHECK_RETURN(size_expr_opt.has_value());
2272+
size_expr = std::move(size_expr_opt.value());
2273+
}
2274+
2275+
irep_idt id = identifier == CPROVER_PREFIX "r_ok" ? ID_r_ok
2276+
: identifier == CPROVER_PREFIX "w_ok" ? ID_w_ok
2277+
: ID_rw_ok;
2278+
2279+
r_or_w_ok_exprt ok_expr(id, pointer_expr, size_expr);
2280+
ok_expr.add_source_location() = expr.source_location();
2281+
2282+
expr.swap(ok_expr);
2283+
return;
2284+
}
22212285
else if(
22222286
auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin(
22232287
identifier, expr.arguments(), f_op.source_location()))
@@ -3145,70 +3209,6 @@ exprt c_typecheck_baset::do_special_functions(
31453209

31463210
return std::move(malloc_expr);
31473211
}
3148-
else if(
3149-
identifier == CPROVER_PREFIX "r_ok" ||
3150-
identifier == CPROVER_PREFIX "w_ok" || identifier == CPROVER_PREFIX "rw_ok")
3151-
{
3152-
if(expr.arguments().size() != 1 && expr.arguments().size() != 2)
3153-
{
3154-
error().source_location = f_op.source_location();
3155-
error() << identifier << " expects one or two operands" << eom;
3156-
throw 0;
3157-
}
3158-
3159-
typecheck_function_call_arguments(expr);
3160-
3161-
// the first argument must be a pointer
3162-
const auto &pointer_expr = expr.arguments()[0];
3163-
if(pointer_expr.type().id() != ID_pointer)
3164-
{
3165-
error().source_location = f_op.source_location();
3166-
error() << identifier << " expects a pointer as first argument" << eom;
3167-
throw 0;
3168-
}
3169-
3170-
// The second argument, when given, is a size_t.
3171-
// When not given, use the pointer subtype.
3172-
exprt size_expr;
3173-
3174-
if(expr.arguments().size() == 2)
3175-
{
3176-
implicit_typecast(expr.arguments()[1], size_type());
3177-
size_expr = expr.arguments()[1];
3178-
}
3179-
else
3180-
{
3181-
// Won't do void *
3182-
const auto &subtype = to_pointer_type(pointer_expr.type()).base_type();
3183-
if(subtype.id() == ID_empty)
3184-
{
3185-
error().source_location = f_op.source_location();
3186-
error() << identifier << " expects a size when given a void pointer"
3187-
<< eom;
3188-
throw 0;
3189-
}
3190-
3191-
auto size_expr_opt = size_of_expr(subtype, *this);
3192-
if(!size_expr_opt.has_value())
3193-
{
3194-
error().source_location = f_op.source_location();
3195-
error() << identifier << " was given object pointer without size"
3196-
<< eom;
3197-
throw 0;
3198-
}
3199-
3200-
size_expr = std::move(size_expr_opt.value());
3201-
}
3202-
3203-
irep_idt id = identifier == CPROVER_PREFIX "r_ok"
3204-
? ID_r_ok
3205-
: identifier == CPROVER_PREFIX "w_ok" ? ID_w_ok : ID_rw_ok;
3206-
3207-
r_or_w_ok_exprt ok_expr(id, pointer_expr, size_expr);
3208-
ok_expr.add_source_location() = source_location;
3209-
3210-
return std::move(ok_expr);
3211-
}
32123212
else if(
32133213
(identifier == CPROVER_PREFIX "old") ||
32143214
(identifier == CPROVER_PREFIX "loop_entry"))

0 commit comments

Comments
 (0)