@@ -2218,6 +2218,70 @@ 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+ throw invalid_source_file_exceptiont{
2229+ id2string (identifier) + " expects one or two operands" ,
2230+ f_op.source_location ()};
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+ throw invalid_source_file_exceptiont{
2244+ id2string (identifier) + " expects a pointer as first argument" ,
2245+ f_op.source_location ()};
2246+ }
2247+
2248+ // The second argument, when given, is a size_t.
2249+ // When not given, use the pointer subtype.
2250+ exprt size_expr;
2251+
2252+ if (expr.arguments ().size () == 2 )
2253+ {
2254+ implicit_typecast (expr.arguments ()[1 ], size_type ());
2255+ size_expr = expr.arguments ()[1 ];
2256+ }
2257+ else
2258+ {
2259+ // Won't do void *
2260+ const auto &subtype =
2261+ to_pointer_type (pointer_expr.type ()).base_type ();
2262+ if (subtype.id () == ID_empty)
2263+ {
2264+ throw invalid_source_file_exceptiont{
2265+ id2string (identifier) +
2266+ " expects a size when given a void pointer" ,
2267+ f_op.source_location ()};
2268+ }
2269+
2270+ auto size_expr_opt = size_of_expr (subtype, *this );
2271+ CHECK_RETURN (size_expr_opt.has_value ());
2272+ size_expr = std::move (size_expr_opt.value ());
2273+ }
2274+
2275+ irep_idt id = identifier == CPROVER_PREFIX " r_ok" ? ID_r_ok
2276+ : identifier == CPROVER_PREFIX " w_ok" ? ID_w_ok
2277+ : ID_rw_ok;
2278+
2279+ r_or_w_ok_exprt ok_expr (id, pointer_expr, size_expr);
2280+ ok_expr.add_source_location () = expr.source_location ();
2281+
2282+ expr.swap (ok_expr);
2283+ return ;
2284+ }
22212285 else if (
22222286 auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin (
22232287 identifier, expr.arguments (), f_op.source_location ()))
@@ -3145,70 +3209,6 @@ exprt c_typecheck_baset::do_special_functions(
31453209
31463210 return std::move (malloc_expr);
31473211 }
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- }
32123212 else if (
32133213 (identifier == CPROVER_PREFIX " old" ) ||
32143214 (identifier == CPROVER_PREFIX " loop_entry" ))
0 commit comments