@@ -2118,6 +2118,106 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
2118
2118
2119
2119
return ;
2120
2120
}
2121
+ else if (identifier == CPROVER_PREFIX " equal" )
2122
+ {
2123
+ if (expr.arguments ().size () != 2 )
2124
+ {
2125
+ error ().source_location = f_op.source_location ();
2126
+ error () << " equal expects two operands" << eom;
2127
+ throw 0 ;
2128
+ }
2129
+
2130
+ equal_exprt equality_expr (
2131
+ expr.arguments ().front (), expr.arguments ().back ());
2132
+ equality_expr.add_source_location () = expr.source_location ();
2133
+
2134
+ if (equality_expr.lhs ().type () != equality_expr.rhs ().type ())
2135
+ {
2136
+ error ().source_location = f_op.source_location ();
2137
+ error () << " equal expects two operands of same type" << eom;
2138
+ throw 0 ;
2139
+ }
2140
+
2141
+ expr.swap (equality_expr);
2142
+ return ;
2143
+ }
2144
+ else if (
2145
+ identifier == CPROVER_PREFIX " overflow_minus" ||
2146
+ identifier == CPROVER_PREFIX " overflow_mult" ||
2147
+ identifier == CPROVER_PREFIX " overflow_plus" ||
2148
+ identifier == CPROVER_PREFIX " overflow_shl" )
2149
+ {
2150
+ exprt overflow{identifier, typet{}, exprt::operandst{expr.arguments ()}};
2151
+ overflow.add_source_location () = f_op.source_location ();
2152
+
2153
+ if (identifier == CPROVER_PREFIX " overflow_minus" )
2154
+ {
2155
+ overflow.id (ID_minus);
2156
+ typecheck_expr_binary_arithmetic (overflow);
2157
+ }
2158
+ else if (identifier == CPROVER_PREFIX " overflow_mult" )
2159
+ {
2160
+ overflow.id (ID_mult);
2161
+ typecheck_expr_binary_arithmetic (overflow);
2162
+ }
2163
+ else if (identifier == CPROVER_PREFIX " overflow_plus" )
2164
+ {
2165
+ overflow.id (ID_plus);
2166
+ typecheck_expr_binary_arithmetic (overflow);
2167
+ }
2168
+ else if (identifier == CPROVER_PREFIX " overflow_shl" )
2169
+ {
2170
+ overflow.id (ID_shl);
2171
+ typecheck_expr_shifts (to_shift_expr (overflow));
2172
+ }
2173
+
2174
+ binary_overflow_exprt of{
2175
+ overflow.operands ()[0 ], overflow.id (), overflow.operands ()[1 ]};
2176
+ of.add_source_location () = overflow.source_location ();
2177
+ expr.swap (of);
2178
+ return ;
2179
+ }
2180
+ else if (identifier == CPROVER_PREFIX " overflow_unary_minus" )
2181
+ {
2182
+ exprt tmp{ID_unary_minus, typet{}, exprt::operandst{expr.arguments ()}};
2183
+ tmp.add_source_location () = f_op.source_location ();
2184
+
2185
+ typecheck_expr_unary_arithmetic (tmp);
2186
+
2187
+ unary_minus_overflow_exprt overflow{tmp.operands ().front ()};
2188
+ overflow.add_source_location () = tmp.source_location ();
2189
+ expr.swap (overflow);
2190
+ return ;
2191
+ }
2192
+ else if (identifier == CPROVER_PREFIX " enum_is_in_range" )
2193
+ {
2194
+ // Check correct number of arguments
2195
+ if (expr.arguments ().size () != 1 )
2196
+ {
2197
+ std::ostringstream error_message;
2198
+ error_message << identifier << " takes exactly 1 argument, but "
2199
+ << expr.arguments ().size () << " were provided" ;
2200
+ throw invalid_source_file_exceptiont{
2201
+ error_message.str (), expr.source_location ()};
2202
+ }
2203
+ const auto &arg1 = expr.arguments ()[0 ];
2204
+ if (!can_cast_type<c_enum_tag_typet>(arg1.type ()))
2205
+ {
2206
+ // Can't enum range check a non-enum
2207
+ std::ostringstream error_message;
2208
+ error_message << identifier << " expects enum, but ("
2209
+ << expr2c (arg1, *this ) << " ) has type `"
2210
+ << type2c (arg1.type (), *this ) << ' `' ;
2211
+ throw invalid_source_file_exceptiont{
2212
+ error_message.str (), expr.source_location ()};
2213
+ }
2214
+
2215
+ enum_is_in_range_exprt in_range{arg1};
2216
+ in_range.add_source_location () = expr.source_location ();
2217
+ exprt lowered = in_range.lower (*this );
2218
+ expr.swap (lowered);
2219
+ return ;
2220
+ }
2121
2221
else if (
2122
2222
auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin (
2123
2223
identifier, expr.arguments (), f_op.source_location ()))
@@ -2534,11 +2634,15 @@ exprt c_typecheck_baset::do_special_functions(
2534
2634
2535
2635
typecheck_function_call_arguments (expr);
2536
2636
2637
+ exprt::operandst args_no_cast;
2638
+ args_no_cast.reserve (expr.arguments ().size ());
2537
2639
for (const auto &argument : expr.arguments ())
2538
2640
{
2641
+ args_no_cast.push_back (skip_typecast (argument));
2539
2642
if (
2540
- argument.type ().id () != ID_pointer ||
2541
- to_pointer_type (argument.type ()).base_type ().id () != ID_struct_tag)
2643
+ args_no_cast.back ().type ().id () != ID_pointer ||
2644
+ to_pointer_type (args_no_cast.back ().type ()).base_type ().id () !=
2645
+ ID_struct_tag)
2542
2646
{
2543
2647
error ().source_location = expr.arguments ()[0 ].source_location ();
2544
2648
error () << " is_sentinel_dll_node expects struct-pointer operands"
@@ -2548,7 +2652,7 @@ exprt c_typecheck_baset::do_special_functions(
2548
2652
}
2549
2653
2550
2654
predicate_exprt is_sentinel_dll_expr (" is_sentinel_dll" );
2551
- is_sentinel_dll_expr.operands () = expr. arguments () ;
2655
+ is_sentinel_dll_expr.operands () = args_no_cast ;
2552
2656
is_sentinel_dll_expr.add_source_location () = source_location;
2553
2657
2554
2658
return std::move (is_sentinel_dll_expr);
@@ -3324,30 +3428,6 @@ exprt c_typecheck_baset::do_special_functions(
3324
3428
3325
3429
return std::move (ffs );
3326
3430
}
3327
- else if (identifier==CPROVER_PREFIX " equal" )
3328
- {
3329
- if (expr.arguments ().size ()!=2 )
3330
- {
3331
- error ().source_location = f_op.source_location ();
3332
- error () << " equal expects two operands" << eom;
3333
- throw 0 ;
3334
- }
3335
-
3336
- typecheck_function_call_arguments (expr);
3337
-
3338
- equal_exprt equality_expr (
3339
- expr.arguments ().front (), expr.arguments ().back ());
3340
- equality_expr.add_source_location ()=source_location;
3341
-
3342
- if (equality_expr.lhs ().type () != equality_expr.rhs ().type ())
3343
- {
3344
- error ().source_location = f_op.source_location ();
3345
- error () << " equal expects two operands of same type" << eom;
3346
- throw 0 ;
3347
- }
3348
-
3349
- return std::move (equality_expr);
3350
- }
3351
3431
else if (identifier==" __builtin_expect" )
3352
3432
{
3353
3433
// This is a gcc extension to provide branch prediction.
@@ -3533,80 +3613,6 @@ exprt c_typecheck_baset::do_special_functions(
3533
3613
3534
3614
return tmp;
3535
3615
}
3536
- else if (
3537
- identifier == CPROVER_PREFIX " overflow_minus" ||
3538
- identifier == CPROVER_PREFIX " overflow_mult" ||
3539
- identifier == CPROVER_PREFIX " overflow_plus" ||
3540
- identifier == CPROVER_PREFIX " overflow_shl" )
3541
- {
3542
- exprt overflow{identifier, typet{}, exprt::operandst{expr.arguments ()}};
3543
- overflow.add_source_location () = f_op.source_location ();
3544
-
3545
- if (identifier == CPROVER_PREFIX " overflow_minus" )
3546
- {
3547
- overflow.id (ID_minus);
3548
- typecheck_expr_binary_arithmetic (overflow);
3549
- }
3550
- else if (identifier == CPROVER_PREFIX " overflow_mult" )
3551
- {
3552
- overflow.id (ID_mult);
3553
- typecheck_expr_binary_arithmetic (overflow);
3554
- }
3555
- else if (identifier == CPROVER_PREFIX " overflow_plus" )
3556
- {
3557
- overflow.id (ID_plus);
3558
- typecheck_expr_binary_arithmetic (overflow);
3559
- }
3560
- else if (identifier == CPROVER_PREFIX " overflow_shl" )
3561
- {
3562
- overflow.id (ID_shl);
3563
- typecheck_expr_shifts (to_shift_expr (overflow));
3564
- }
3565
-
3566
- binary_overflow_exprt of{
3567
- overflow.operands ()[0 ], overflow.id (), overflow.operands ()[1 ]};
3568
- of.add_source_location () = overflow.source_location ();
3569
- return std::move (of);
3570
- }
3571
- else if (identifier == CPROVER_PREFIX " overflow_unary_minus" )
3572
- {
3573
- exprt tmp{ID_unary_minus, typet{}, exprt::operandst{expr.arguments ()}};
3574
- tmp.add_source_location () = f_op.source_location ();
3575
-
3576
- typecheck_expr_unary_arithmetic (tmp);
3577
-
3578
- unary_minus_overflow_exprt overflow{tmp.operands ().front ()};
3579
- overflow.add_source_location () = tmp.source_location ();
3580
- return std::move (overflow);
3581
- }
3582
- else if (identifier == CPROVER_PREFIX " enum_is_in_range" )
3583
- {
3584
- // Check correct number of arguments
3585
- if (expr.arguments ().size () != 1 )
3586
- {
3587
- std::ostringstream error_message;
3588
- error_message << identifier << " takes exactly 1 argument, but "
3589
- << expr.arguments ().size () << " were provided" ;
3590
- throw invalid_source_file_exceptiont{
3591
- error_message.str (), expr.source_location ()};
3592
- }
3593
- auto arg1 = expr.arguments ()[0 ];
3594
- typecheck_expr (arg1);
3595
- if (!can_cast_type<c_enum_tag_typet>(arg1.type ()))
3596
- {
3597
- // Can't enum range check a non-enum
3598
- std::ostringstream error_message;
3599
- error_message << identifier << " expects enum, but ("
3600
- << expr2c (arg1, *this ) << " ) has type `"
3601
- << type2c (arg1.type (), *this ) << ' `' ;
3602
- throw invalid_source_file_exceptiont{
3603
- error_message.str (), expr.source_location ()};
3604
- }
3605
- else
3606
- {
3607
- return expr;
3608
- }
3609
- }
3610
3616
else if (
3611
3617
identifier == " __builtin_add_overflow" ||
3612
3618
identifier == " __builtin_sadd_overflow" ||
0 commit comments