@@ -2118,6 +2118,106 @@ void c_typecheck_baset::typecheck_side_effect_function_call(
21182118
21192119 return ;
21202120 }
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+ }
21212221 else if (
21222222 auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin (
21232223 identifier, expr.arguments (), f_op.source_location ()))
@@ -2534,11 +2634,15 @@ exprt c_typecheck_baset::do_special_functions(
25342634
25352635 typecheck_function_call_arguments (expr);
25362636
2637+ exprt::operandst args_no_cast;
2638+ args_no_cast.reserve (expr.arguments ().size ());
25372639 for (const auto &argument : expr.arguments ())
25382640 {
2641+ args_no_cast.push_back (skip_typecast (argument));
25392642 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)
25422646 {
25432647 error ().source_location = expr.arguments ()[0 ].source_location ();
25442648 error () << " is_sentinel_dll_node expects struct-pointer operands"
@@ -2548,7 +2652,7 @@ exprt c_typecheck_baset::do_special_functions(
25482652 }
25492653
25502654 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 ;
25522656 is_sentinel_dll_expr.add_source_location () = source_location;
25532657
25542658 return std::move (is_sentinel_dll_expr);
@@ -3324,30 +3428,6 @@ exprt c_typecheck_baset::do_special_functions(
33243428
33253429 return std::move (ffs);
33263430 }
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- }
33513431 else if (identifier==" __builtin_expect" )
33523432 {
33533433 // This is a gcc extension to provide branch prediction.
@@ -3533,80 +3613,6 @@ exprt c_typecheck_baset::do_special_functions(
35333613
35343614 return tmp;
35353615 }
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- }
36103616 else if (
36113617 identifier == " __builtin_add_overflow" ||
36123618 identifier == " __builtin_sadd_overflow" ||
0 commit comments