@@ -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