Skip to content

Commit f2733dc

Browse files
tautschnigDaniel Kroening
authored and
Daniel Kroening
committed
C front-end: type check arguments to built-in functions
We only sometimes did this, effectively relying on all other cases not requiring any modifications to the expression by the type checker. The case of passing an array to __CPROVER_{r,w}_ok showed that this wasn't sufficient. Now fixed for all built-in functions handled by the type checker.
1 parent 09875c3 commit f2733dc

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

regression/cbmc/r_w_ok4/main.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
int main()
5+
{
6+
int A[1];
7+
8+
assert(__CPROVER_r_ok(A, sizeof(int)));
9+
}

regression/cbmc/r_w_ok4/test.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^VERIFICATION SUCCESSFUL$
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring

src/ansi-c/c_typecheck_expr.cpp

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,8 @@ exprt c_typecheck_baset::do_special_functions(
20562056
throw 0;
20572057
}
20582058

2059+
typecheck_function_call_arguments(expr);
2060+
20592061
exprt same_object_expr=
20602062
same_object(expr.arguments()[0], expr.arguments()[1]);
20612063
same_object_expr.add_source_location()=source_location;
@@ -2105,6 +2107,8 @@ exprt c_typecheck_baset::do_special_functions(
21052107
throw 0;
21062108
}
21072109

2110+
typecheck_function_call_arguments(expr);
2111+
21082112
exprt same_object_expr = is_invalid_pointer_exprt{expr.arguments().front()};
21092113
same_object_expr.add_source_location()=source_location;
21102114

@@ -2119,6 +2123,8 @@ exprt c_typecheck_baset::do_special_functions(
21192123
throw 0;
21202124
}
21212125

2126+
typecheck_function_call_arguments(expr);
2127+
21222128
exprt buffer_size_expr("buffer_size", size_type());
21232129
buffer_size_expr.operands()=expr.arguments();
21242130
buffer_size_expr.add_source_location()=source_location;
@@ -2134,6 +2140,8 @@ exprt c_typecheck_baset::do_special_functions(
21342140
throw 0;
21352141
}
21362142

2143+
typecheck_function_call_arguments(expr);
2144+
21372145
predicate_exprt is_zero_string_expr("is_zero_string");
21382146
is_zero_string_expr.operands()=expr.arguments();
21392147
is_zero_string_expr.set(ID_C_lvalue, true); // make it an lvalue
@@ -2150,6 +2158,8 @@ exprt c_typecheck_baset::do_special_functions(
21502158
throw 0;
21512159
}
21522160

2161+
typecheck_function_call_arguments(expr);
2162+
21532163
exprt zero_string_length_expr("zero_string_length", size_type());
21542164
zero_string_length_expr.operands()=expr.arguments();
21552165
zero_string_length_expr.set(ID_C_lvalue, true); // make it an lvalue
@@ -2166,6 +2176,8 @@ exprt c_typecheck_baset::do_special_functions(
21662176
throw 0;
21672177
}
21682178

2179+
typecheck_function_call_arguments(expr);
2180+
21692181
exprt is_dynamic_object_expr = is_dynamic_object_exprt(expr.arguments()[0]);
21702182
is_dynamic_object_expr.add_source_location() = source_location;
21712183

@@ -2180,6 +2192,8 @@ exprt c_typecheck_baset::do_special_functions(
21802192
throw 0;
21812193
}
21822194

2195+
typecheck_function_call_arguments(expr);
2196+
21832197
exprt pointer_offset_expr=pointer_offset(expr.arguments().front());
21842198
pointer_offset_expr.add_source_location()=source_location;
21852199

@@ -2194,6 +2208,8 @@ exprt c_typecheck_baset::do_special_functions(
21942208
throw 0;
21952209
}
21962210

2211+
typecheck_function_call_arguments(expr);
2212+
21972213
unary_exprt object_size_expr(
21982214
ID_object_size, expr.arguments()[0], size_type());
21992215
object_size_expr.add_source_location() = source_location;
@@ -2209,6 +2225,8 @@ exprt c_typecheck_baset::do_special_functions(
22092225
throw 0;
22102226
}
22112227

2228+
typecheck_function_call_arguments(expr);
2229+
22122230
exprt pointer_object_expr = pointer_object(expr.arguments().front());
22132231
pointer_object_expr.add_source_location() = source_location;
22142232

@@ -2218,15 +2236,15 @@ exprt c_typecheck_baset::do_special_functions(
22182236
identifier=="__builtin_bswap32" ||
22192237
identifier=="__builtin_bswap64")
22202238
{
2221-
typecheck_function_call_arguments(expr);
2222-
22232239
if(expr.arguments().size()!=1)
22242240
{
22252241
error().source_location = f_op.source_location();
22262242
error() << identifier << " expects one operand" << eom;
22272243
throw 0;
22282244
}
22292245

2246+
typecheck_function_call_arguments(expr);
2247+
22302248
// these are hard-wired to 8 bits according to the gcc manual
22312249
bswap_exprt bswap_expr(expr.arguments().front(), 8, expr.type());
22322250
bswap_expr.add_source_location()=source_location;
@@ -2235,15 +2253,15 @@ exprt c_typecheck_baset::do_special_functions(
22352253
}
22362254
else if(identifier=="__builtin_nontemporal_load")
22372255
{
2238-
typecheck_function_call_arguments(expr);
2239-
22402256
if(expr.arguments().size()!=1)
22412257
{
22422258
error().source_location = f_op.source_location();
22432259
error() << identifier << " expects one operand" << eom;
22442260
throw 0;
22452261
}
22462262

2263+
typecheck_function_call_arguments(expr);
2264+
22472265
// these return the subtype of the argument
22482266
exprt &ptr_arg=expr.arguments().front();
22492267

@@ -2269,6 +2287,8 @@ exprt c_typecheck_baset::do_special_functions(
22692287
throw 0;
22702288
}
22712289

2290+
typecheck_function_call_arguments(expr);
2291+
22722292
// This gets 5 integers followed by a float or double.
22732293
// The five integers are the return values for the cases
22742294
// FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL and FP_ZERO.
@@ -2315,6 +2335,8 @@ exprt c_typecheck_baset::do_special_functions(
23152335
throw 0;
23162336
}
23172337

2338+
typecheck_function_call_arguments(expr);
2339+
23182340
isnan_exprt isnan_expr(expr.arguments().front());
23192341
isnan_expr.add_source_location()=source_location;
23202342

@@ -2331,6 +2353,8 @@ exprt c_typecheck_baset::do_special_functions(
23312353
throw 0;
23322354
}
23332355

2356+
typecheck_function_call_arguments(expr);
2357+
23342358
isfinite_exprt isfinite_expr(expr.arguments().front());
23352359
isfinite_expr.add_source_location()=source_location;
23362360

@@ -2378,6 +2402,8 @@ exprt c_typecheck_baset::do_special_functions(
23782402
throw 0;
23792403
}
23802404

2405+
typecheck_function_call_arguments(expr);
2406+
23812407
abs_exprt abs_expr(expr.arguments().front());
23822408
abs_expr.add_source_location()=source_location;
23832409

@@ -2392,6 +2418,8 @@ exprt c_typecheck_baset::do_special_functions(
23922418
throw 0;
23932419
}
23942420

2421+
typecheck_function_call_arguments(expr);
2422+
23952423
side_effect_exprt malloc_expr(ID_allocate, expr.type(), source_location);
23962424
malloc_expr.operands()=expr.arguments();
23972425

@@ -2407,6 +2435,8 @@ exprt c_typecheck_baset::do_special_functions(
24072435
throw 0;
24082436
}
24092437

2438+
typecheck_function_call_arguments(expr);
2439+
24102440
irep_idt id = identifier == CPROVER_PREFIX "r_ok" ? ID_r_ok : ID_w_ok;
24112441

24122442
binary_predicate_exprt ok_expr(
@@ -2427,6 +2457,8 @@ exprt c_typecheck_baset::do_special_functions(
24272457
throw 0;
24282458
}
24292459

2460+
typecheck_function_call_arguments(expr);
2461+
24302462
isinf_exprt isinf_expr(expr.arguments().front());
24312463
isinf_expr.add_source_location()=source_location;
24322464

@@ -2441,6 +2473,8 @@ exprt c_typecheck_baset::do_special_functions(
24412473
throw 0;
24422474
}
24432475

2476+
typecheck_function_call_arguments(expr);
2477+
24442478
// returns 1 for +inf and -1 for -inf, and 0 otherwise
24452479

24462480
const exprt &fp_value = expr.arguments().front();
@@ -2468,6 +2502,8 @@ exprt c_typecheck_baset::do_special_functions(
24682502
throw 0;
24692503
}
24702504

2505+
typecheck_function_call_arguments(expr);
2506+
24712507
const exprt &fp_value = expr.arguments()[0];
24722508

24732509
if(fp_value.type().id() != ID_floatbv)
@@ -2496,6 +2532,8 @@ exprt c_typecheck_baset::do_special_functions(
24962532
throw 0;
24972533
}
24982534

2535+
typecheck_function_call_arguments(expr);
2536+
24992537
sign_exprt sign_expr(expr.arguments().front());
25002538
sign_expr.add_source_location()=source_location;
25012539

@@ -2515,6 +2553,8 @@ exprt c_typecheck_baset::do_special_functions(
25152553
throw 0;
25162554
}
25172555

2556+
typecheck_function_call_arguments(expr);
2557+
25182558
popcount_exprt popcount_expr(expr.arguments().front(), expr.type());
25192559
popcount_expr.add_source_location()=source_location;
25202560

@@ -2529,6 +2569,8 @@ exprt c_typecheck_baset::do_special_functions(
25292569
throw 0;
25302570
}
25312571

2572+
typecheck_function_call_arguments(expr);
2573+
25322574
equal_exprt equality_expr(
25332575
expr.arguments().front(), expr.arguments().back());
25342576
equality_expr.add_source_location()=source_location;
@@ -2557,6 +2599,8 @@ exprt c_typecheck_baset::do_special_functions(
25572599
throw 0;
25582600
}
25592601

2602+
typecheck_function_call_arguments(expr);
2603+
25602604
return typecast_exprt(expr.arguments()[0], expr.type());
25612605
}
25622606
else if(identifier=="__builtin_object_size")
@@ -2572,6 +2616,8 @@ exprt c_typecheck_baset::do_special_functions(
25722616
throw 0;
25732617
}
25742618

2619+
typecheck_function_call_arguments(expr);
2620+
25752621
make_constant(expr.arguments()[1]);
25762622

25772623
mp_integer arg1;
@@ -2614,6 +2660,8 @@ exprt c_typecheck_baset::do_special_functions(
26142660
throw 0;
26152661
}
26162662

2663+
typecheck_function_call_arguments(expr);
2664+
26172665
exprt arg0 =
26182666
typecast_exprt::conditional_cast(expr.arguments()[0], bool_typet());
26192667
make_constant(arg0);
@@ -2634,6 +2682,9 @@ exprt c_typecheck_baset::do_special_functions(
26342682
throw 0;
26352683
}
26362684

2685+
// do not typecheck the argument - it is never evaluated, and thus side
2686+
// effects must not show up either
2687+
26372688
// try to produce constant
26382689
exprt tmp1=expr.arguments().front();
26392690
simplify(tmp1, *this);
@@ -2671,6 +2722,8 @@ exprt c_typecheck_baset::do_special_functions(
26712722
throw 0;
26722723
}
26732724

2725+
typecheck_function_call_arguments(expr);
2726+
26742727
exprt object=expr.arguments()[0];
26752728

26762729
// The value doesn't matter at all, we only care about the type.
@@ -2743,6 +2796,8 @@ exprt c_typecheck_baset::do_special_functions(
27432796
throw 0;
27442797
}
27452798

2799+
typecheck_function_call_arguments(expr);
2800+
27462801
exprt &ptr_arg=expr.arguments().front();
27472802

27482803
if(ptr_arg.type().id()!=ID_pointer)

0 commit comments

Comments
 (0)