Skip to content

Commit 8aed383

Browse files
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 9dbac2e commit 8aed383

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
@@ -2052,6 +2052,8 @@ exprt c_typecheck_baset::do_special_functions(
20522052
throw 0;
20532053
}
20542054

2055+
typecheck_function_call_arguments(expr);
2056+
20552057
exprt same_object_expr=
20562058
same_object(expr.arguments()[0], expr.arguments()[1]);
20572059
same_object_expr.add_source_location()=source_location;
@@ -2101,6 +2103,8 @@ exprt c_typecheck_baset::do_special_functions(
21012103
throw 0;
21022104
}
21032105

2106+
typecheck_function_call_arguments(expr);
2107+
21042108
exprt same_object_expr = is_invalid_pointer_exprt{expr.arguments().front()};
21052109
same_object_expr.add_source_location()=source_location;
21062110

@@ -2115,6 +2119,8 @@ exprt c_typecheck_baset::do_special_functions(
21152119
throw 0;
21162120
}
21172121

2122+
typecheck_function_call_arguments(expr);
2123+
21182124
exprt buffer_size_expr("buffer_size", size_type());
21192125
buffer_size_expr.operands()=expr.arguments();
21202126
buffer_size_expr.add_source_location()=source_location;
@@ -2130,6 +2136,8 @@ exprt c_typecheck_baset::do_special_functions(
21302136
throw 0;
21312137
}
21322138

2139+
typecheck_function_call_arguments(expr);
2140+
21332141
predicate_exprt is_zero_string_expr("is_zero_string");
21342142
is_zero_string_expr.operands()=expr.arguments();
21352143
is_zero_string_expr.set(ID_C_lvalue, true); // make it an lvalue
@@ -2146,6 +2154,8 @@ exprt c_typecheck_baset::do_special_functions(
21462154
throw 0;
21472155
}
21482156

2157+
typecheck_function_call_arguments(expr);
2158+
21492159
exprt zero_string_length_expr("zero_string_length", size_type());
21502160
zero_string_length_expr.operands()=expr.arguments();
21512161
zero_string_length_expr.set(ID_C_lvalue, true); // make it an lvalue
@@ -2162,6 +2172,8 @@ exprt c_typecheck_baset::do_special_functions(
21622172
throw 0;
21632173
}
21642174

2175+
typecheck_function_call_arguments(expr);
2176+
21652177
exprt is_dynamic_object_expr = is_dynamic_object_exprt(expr.arguments()[0]);
21662178
is_dynamic_object_expr.add_source_location() = source_location;
21672179

@@ -2176,6 +2188,8 @@ exprt c_typecheck_baset::do_special_functions(
21762188
throw 0;
21772189
}
21782190

2191+
typecheck_function_call_arguments(expr);
2192+
21792193
exprt pointer_offset_expr=pointer_offset(expr.arguments().front());
21802194
pointer_offset_expr.add_source_location()=source_location;
21812195

@@ -2190,6 +2204,8 @@ exprt c_typecheck_baset::do_special_functions(
21902204
throw 0;
21912205
}
21922206

2207+
typecheck_function_call_arguments(expr);
2208+
21932209
unary_exprt object_size_expr(
21942210
ID_object_size, expr.arguments()[0], size_type());
21952211
object_size_expr.add_source_location() = source_location;
@@ -2205,6 +2221,8 @@ exprt c_typecheck_baset::do_special_functions(
22052221
throw 0;
22062222
}
22072223

2224+
typecheck_function_call_arguments(expr);
2225+
22082226
exprt pointer_object_expr = pointer_object(expr.arguments().front());
22092227
pointer_object_expr.add_source_location() = source_location;
22102228

@@ -2214,15 +2232,15 @@ exprt c_typecheck_baset::do_special_functions(
22142232
identifier=="__builtin_bswap32" ||
22152233
identifier=="__builtin_bswap64")
22162234
{
2217-
typecheck_function_call_arguments(expr);
2218-
22192235
if(expr.arguments().size()!=1)
22202236
{
22212237
error().source_location = f_op.source_location();
22222238
error() << identifier << " expects one operand" << eom;
22232239
throw 0;
22242240
}
22252241

2242+
typecheck_function_call_arguments(expr);
2243+
22262244
// these are hard-wired to 8 bits according to the gcc manual
22272245
bswap_exprt bswap_expr(expr.arguments().front(), 8, expr.type());
22282246
bswap_expr.add_source_location()=source_location;
@@ -2231,15 +2249,15 @@ exprt c_typecheck_baset::do_special_functions(
22312249
}
22322250
else if(identifier=="__builtin_nontemporal_load")
22332251
{
2234-
typecheck_function_call_arguments(expr);
2235-
22362252
if(expr.arguments().size()!=1)
22372253
{
22382254
error().source_location = f_op.source_location();
22392255
error() << identifier << " expects one operand" << eom;
22402256
throw 0;
22412257
}
22422258

2259+
typecheck_function_call_arguments(expr);
2260+
22432261
// these return the subtype of the argument
22442262
exprt &ptr_arg=expr.arguments().front();
22452263

@@ -2265,6 +2283,8 @@ exprt c_typecheck_baset::do_special_functions(
22652283
throw 0;
22662284
}
22672285

2286+
typecheck_function_call_arguments(expr);
2287+
22682288
// This gets 5 integers followed by a float or double.
22692289
// The five integers are the return values for the cases
22702290
// FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL and FP_ZERO.
@@ -2311,6 +2331,8 @@ exprt c_typecheck_baset::do_special_functions(
23112331
throw 0;
23122332
}
23132333

2334+
typecheck_function_call_arguments(expr);
2335+
23142336
isnan_exprt isnan_expr(expr.arguments().front());
23152337
isnan_expr.add_source_location()=source_location;
23162338

@@ -2327,6 +2349,8 @@ exprt c_typecheck_baset::do_special_functions(
23272349
throw 0;
23282350
}
23292351

2352+
typecheck_function_call_arguments(expr);
2353+
23302354
isfinite_exprt isfinite_expr(expr.arguments().front());
23312355
isfinite_expr.add_source_location()=source_location;
23322356

@@ -2374,6 +2398,8 @@ exprt c_typecheck_baset::do_special_functions(
23742398
throw 0;
23752399
}
23762400

2401+
typecheck_function_call_arguments(expr);
2402+
23772403
abs_exprt abs_expr(expr.arguments().front());
23782404
abs_expr.add_source_location()=source_location;
23792405

@@ -2388,6 +2414,8 @@ exprt c_typecheck_baset::do_special_functions(
23882414
throw 0;
23892415
}
23902416

2417+
typecheck_function_call_arguments(expr);
2418+
23912419
side_effect_exprt malloc_expr(ID_allocate, expr.type(), source_location);
23922420
malloc_expr.operands()=expr.arguments();
23932421

@@ -2403,6 +2431,8 @@ exprt c_typecheck_baset::do_special_functions(
24032431
throw 0;
24042432
}
24052433

2434+
typecheck_function_call_arguments(expr);
2435+
24062436
irep_idt id = identifier == CPROVER_PREFIX "r_ok" ? ID_r_ok : ID_w_ok;
24072437

24082438
binary_predicate_exprt ok_expr(
@@ -2423,6 +2453,8 @@ exprt c_typecheck_baset::do_special_functions(
24232453
throw 0;
24242454
}
24252455

2456+
typecheck_function_call_arguments(expr);
2457+
24262458
isinf_exprt isinf_expr(expr.arguments().front());
24272459
isinf_expr.add_source_location()=source_location;
24282460

@@ -2437,6 +2469,8 @@ exprt c_typecheck_baset::do_special_functions(
24372469
throw 0;
24382470
}
24392471

2472+
typecheck_function_call_arguments(expr);
2473+
24402474
// returns 1 for +inf and -1 for -inf, and 0 otherwise
24412475

24422476
const exprt &fp_value = expr.arguments().front();
@@ -2464,6 +2498,8 @@ exprt c_typecheck_baset::do_special_functions(
24642498
throw 0;
24652499
}
24662500

2501+
typecheck_function_call_arguments(expr);
2502+
24672503
const exprt &fp_value = expr.arguments()[0];
24682504

24692505
if(fp_value.type().id() != ID_floatbv)
@@ -2492,6 +2528,8 @@ exprt c_typecheck_baset::do_special_functions(
24922528
throw 0;
24932529
}
24942530

2531+
typecheck_function_call_arguments(expr);
2532+
24952533
sign_exprt sign_expr(expr.arguments().front());
24962534
sign_expr.add_source_location()=source_location;
24972535

@@ -2511,6 +2549,8 @@ exprt c_typecheck_baset::do_special_functions(
25112549
throw 0;
25122550
}
25132551

2552+
typecheck_function_call_arguments(expr);
2553+
25142554
popcount_exprt popcount_expr(expr.arguments().front(), expr.type());
25152555
popcount_expr.add_source_location()=source_location;
25162556

@@ -2525,6 +2565,8 @@ exprt c_typecheck_baset::do_special_functions(
25252565
throw 0;
25262566
}
25272567

2568+
typecheck_function_call_arguments(expr);
2569+
25282570
equal_exprt equality_expr(
25292571
expr.arguments().front(), expr.arguments().back());
25302572
equality_expr.add_source_location()=source_location;
@@ -2553,6 +2595,8 @@ exprt c_typecheck_baset::do_special_functions(
25532595
throw 0;
25542596
}
25552597

2598+
typecheck_function_call_arguments(expr);
2599+
25562600
return typecast_exprt(expr.arguments()[0], expr.type());
25572601
}
25582602
else if(identifier=="__builtin_object_size")
@@ -2568,6 +2612,8 @@ exprt c_typecheck_baset::do_special_functions(
25682612
throw 0;
25692613
}
25702614

2615+
typecheck_function_call_arguments(expr);
2616+
25712617
make_constant(expr.arguments()[1]);
25722618

25732619
mp_integer arg1;
@@ -2610,6 +2656,8 @@ exprt c_typecheck_baset::do_special_functions(
26102656
throw 0;
26112657
}
26122658

2659+
typecheck_function_call_arguments(expr);
2660+
26132661
exprt arg0 =
26142662
typecast_exprt::conditional_cast(expr.arguments()[0], bool_typet());
26152663
make_constant(arg0);
@@ -2630,6 +2678,9 @@ exprt c_typecheck_baset::do_special_functions(
26302678
throw 0;
26312679
}
26322680

2681+
// do not typecheck the argument - it is never evaluated, and thus side
2682+
// effects must not show up either
2683+
26332684
// try to produce constant
26342685
exprt tmp1=expr.arguments().front();
26352686
simplify(tmp1, *this);
@@ -2667,6 +2718,8 @@ exprt c_typecheck_baset::do_special_functions(
26672718
throw 0;
26682719
}
26692720

2721+
typecheck_function_call_arguments(expr);
2722+
26702723
exprt object=expr.arguments()[0];
26712724

26722725
// The value doesn't matter at all, we only care about the type.
@@ -2739,6 +2792,8 @@ exprt c_typecheck_baset::do_special_functions(
27392792
throw 0;
27402793
}
27412794

2795+
typecheck_function_call_arguments(expr);
2796+
27422797
exprt &ptr_arg=expr.arguments().front();
27432798

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

0 commit comments

Comments
 (0)