@@ -593,8 +593,20 @@ void goto_convertt::do_array_op(
593593 copy (array_op_statement, OTHER, dest);
594594}
595595
596- exprt make_va_list (const exprt &expr)
596+ static exprt make_va_list (const exprt &expr, const namespacet &ns )
597597{
598+ if (
599+ auto struct_tag_type = type_try_dynamic_cast<struct_tag_typet>(expr.type ()))
600+ {
601+ // aarch64 ABI mandates that va_list has struct type with member names as
602+ // specified
603+ const auto &components = ns.follow_tag (*struct_tag_type).components ();
604+ DATA_INVARIANT (
605+ components.size () == 5 ,
606+ " va_list struct type expected to have 5 components" );
607+ return member_exprt{expr, components.front ()};
608+ }
609+
598610 exprt result = skip_typecast (expr);
599611
600612 // if it's an address of an lvalue, we take that
@@ -1296,14 +1308,15 @@ void goto_convertt::do_function_call_symbol(
12961308 throw 0 ;
12971309 }
12981310
1299- exprt list_arg = make_va_list (arguments[0 ]);
1311+ exprt list_arg = make_va_list (arguments[0 ], ns);
1312+ const bool va_list_is_void_ptr =
1313+ list_arg.type ().id () == ID_pointer &&
1314+ to_pointer_type (list_arg.type ()).base_type ().id () == ID_empty;
13001315
13011316 if (lhs.is_not_nil ())
13021317 {
13031318 exprt list_arg_cast = list_arg;
1304- if (
1305- list_arg.type ().id () == ID_pointer &&
1306- to_pointer_type (list_arg.type ()).base_type ().id () == ID_empty)
1319+ if (va_list_is_void_ptr)
13071320 {
13081321 list_arg_cast =
13091322 typecast_exprt{list_arg, pointer_type (pointer_type (empty_typet{}))};
@@ -1317,8 +1330,14 @@ void goto_convertt::do_function_call_symbol(
13171330 goto_programt::make_assignment (lhs, rhs, function.source_location ()));
13181331 }
13191332
1320- code_assignt assign{
1321- list_arg, plus_exprt{list_arg, from_integer (1 , pointer_diff_type ())}};
1333+ exprt list_arg_ptr_arithmetic = typecast_exprt::conditional_cast (
1334+ plus_exprt{
1335+ (va_list_is_void_ptr
1336+ ? typecast_exprt{list_arg, pointer_type (pointer_type (empty_typet{}))}
1337+ : list_arg),
1338+ from_integer (1 , pointer_diff_type ())},
1339+ list_arg.type ());
1340+ code_assignt assign{list_arg, std::move (list_arg_ptr_arithmetic)};
13221341 assign.rhs ().set (
13231342 ID_C_va_arg_type, to_code_type (function.type ()).return_type ());
13241343 dest.add (goto_programt::make_assignment (
@@ -1333,7 +1352,7 @@ void goto_convertt::do_function_call_symbol(
13331352 throw 0 ;
13341353 }
13351354
1336- exprt dest_expr = make_va_list (arguments[0 ]);
1355+ exprt dest_expr = make_va_list (arguments[0 ], ns );
13371356 const typecast_exprt src_expr (arguments[1 ], dest_expr.type ());
13381357
13391358 if (!is_assignable (dest_expr))
@@ -1357,7 +1376,7 @@ void goto_convertt::do_function_call_symbol(
13571376 throw 0 ;
13581377 }
13591378
1360- exprt dest_expr = make_va_list (arguments[0 ]);
1379+ exprt dest_expr = make_va_list (arguments[0 ], ns );
13611380
13621381 if (!is_assignable (dest_expr))
13631382 {
@@ -1392,7 +1411,7 @@ void goto_convertt::do_function_call_symbol(
13921411 throw 0 ;
13931412 }
13941413
1395- exprt dest_expr = make_va_list (arguments[0 ]);
1414+ exprt dest_expr = make_va_list (arguments[0 ], ns );
13961415
13971416 if (!is_assignable (dest_expr))
13981417 {
0 commit comments