Skip to content

Commit dde7cf4

Browse files
committed
Avoid confusing "__CPROVER_{r,w,rw}_ok is not declared" warning
With 4b05d48 there no longer is a (pseudo-) forward declaration available, making the C front-end warn about this built-in function not being declared. As this is polymorphic, we shouldn't be type checking it as a function in the first place, and instead should give it separate treatment as we do with other polymorphic built-ins.
1 parent d7099ae commit dde7cf4

File tree

3 files changed

+105
-64
lines changed

3 files changed

+105
-64
lines changed

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: 72 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,6 +2218,78 @@ 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+
error().source_location = f_op.source_location();
2229+
error() << identifier << " expects one or two operands" << eom;
2230+
throw 0;
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+
error().source_location = f_op.source_location();
2244+
error() << identifier << " expects a pointer as first argument"
2245+
<< eom;
2246+
throw 0;
2247+
}
2248+
2249+
// The second argument, when given, is a size_t.
2250+
// When not given, use the pointer subtype.
2251+
exprt size_expr;
2252+
2253+
if(expr.arguments().size() == 2)
2254+
{
2255+
implicit_typecast(expr.arguments()[1], size_type());
2256+
size_expr = expr.arguments()[1];
2257+
}
2258+
else
2259+
{
2260+
// Won't do void *
2261+
const auto &subtype =
2262+
to_pointer_type(pointer_expr.type()).base_type();
2263+
if(subtype.id() == ID_empty)
2264+
{
2265+
error().source_location = f_op.source_location();
2266+
error() << identifier << " expects a size when given a void pointer"
2267+
<< eom;
2268+
throw 0;
2269+
}
2270+
2271+
auto size_expr_opt = size_of_expr(subtype, *this);
2272+
if(!size_expr_opt.has_value())
2273+
{
2274+
error().source_location = f_op.source_location();
2275+
error() << identifier << " was given object pointer without size"
2276+
<< eom;
2277+
throw 0;
2278+
}
2279+
2280+
size_expr = std::move(size_expr_opt.value());
2281+
}
2282+
2283+
irep_idt id = identifier == CPROVER_PREFIX "r_ok" ? ID_r_ok
2284+
: identifier == CPROVER_PREFIX "w_ok" ? ID_w_ok
2285+
: ID_rw_ok;
2286+
2287+
r_or_w_ok_exprt ok_expr(id, pointer_expr, size_expr);
2288+
ok_expr.add_source_location() = expr.source_location();
2289+
2290+
expr.swap(ok_expr);
2291+
return;
2292+
}
22212293
else if(
22222294
auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin(
22232295
identifier, expr.arguments(), f_op.source_location()))
@@ -3145,70 +3217,6 @@ exprt c_typecheck_baset::do_special_functions(
31453217

31463218
return std::move(malloc_expr);
31473219
}
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-
}
32123220
else if(
32133221
(identifier == CPROVER_PREFIX "old") ||
32143222
(identifier == CPROVER_PREFIX "loop_entry"))

0 commit comments

Comments
 (0)