@@ -2218,6 +2218,78 @@ 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+ error ().source_location = f_op.source_location ();
2229+ error () << identifier << " expects one or two operands" << eom;
2230+ throw 0 ;
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+ error ().source_location = f_op.source_location ();
2244+ error () << identifier << " expects a pointer as first argument"
2245+ << eom;
2246+ throw 0 ;
2247+ }
2248+
2249+ // The second argument, when given, is a size_t.
2250+ // When not given, use the pointer subtype.
2251+ exprt size_expr;
2252+
2253+ if (expr.arguments ().size () == 2 )
2254+ {
2255+ implicit_typecast (expr.arguments ()[1 ], size_type ());
2256+ size_expr = expr.arguments ()[1 ];
2257+ }
2258+ else
2259+ {
2260+ // Won't do void *
2261+ const auto &subtype =
2262+ to_pointer_type (pointer_expr.type ()).base_type ();
2263+ if (subtype.id () == ID_empty)
2264+ {
2265+ error ().source_location = f_op.source_location ();
2266+ error () << identifier << " expects a size when given a void pointer"
2267+ << eom;
2268+ throw 0 ;
2269+ }
2270+
2271+ auto size_expr_opt = size_of_expr (subtype, *this );
2272+ if (!size_expr_opt.has_value ())
2273+ {
2274+ error ().source_location = f_op.source_location ();
2275+ error () << identifier << " was given object pointer without size"
2276+ << eom;
2277+ throw 0 ;
2278+ }
2279+
2280+ size_expr = std::move (size_expr_opt.value ());
2281+ }
2282+
2283+ irep_idt id = identifier == CPROVER_PREFIX " r_ok" ? ID_r_ok
2284+ : identifier == CPROVER_PREFIX " w_ok" ? ID_w_ok
2285+ : ID_rw_ok;
2286+
2287+ r_or_w_ok_exprt ok_expr (id, pointer_expr, size_expr);
2288+ ok_expr.add_source_location () = expr.source_location ();
2289+
2290+ expr.swap (ok_expr);
2291+ return ;
2292+ }
22212293 else if (
22222294 auto gcc_polymorphic = typecheck_gcc_polymorphic_builtin (
22232295 identifier, expr.arguments (), f_op.source_location ()))
@@ -3145,70 +3217,6 @@ exprt c_typecheck_baset::do_special_functions(
31453217
31463218 return std::move (malloc_expr);
31473219 }
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- }
32123220 else if (
32133221 (identifier == CPROVER_PREFIX " old" ) ||
32143222 (identifier == CPROVER_PREFIX " loop_entry" ))
0 commit comments