@@ -593,8 +593,20 @@ void goto_convertt::do_array_op(
593
593
copy (array_op_statement, OTHER, dest);
594
594
}
595
595
596
- exprt make_va_list (const exprt &expr)
596
+ static exprt make_va_list (const exprt &expr, const namespacet &ns )
597
597
{
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
+
598
610
exprt result = skip_typecast (expr);
599
611
600
612
// if it's an address of an lvalue, we take that
@@ -1296,14 +1308,15 @@ void goto_convertt::do_function_call_symbol(
1296
1308
throw 0 ;
1297
1309
}
1298
1310
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;
1300
1315
1301
1316
if (lhs.is_not_nil ())
1302
1317
{
1303
1318
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)
1307
1320
{
1308
1321
list_arg_cast =
1309
1322
typecast_exprt{list_arg, pointer_type (pointer_type (empty_typet{}))};
@@ -1317,8 +1330,14 @@ void goto_convertt::do_function_call_symbol(
1317
1330
goto_programt::make_assignment (lhs, rhs, function.source_location ()));
1318
1331
}
1319
1332
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)};
1322
1341
assign.rhs ().set (
1323
1342
ID_C_va_arg_type, to_code_type (function.type ()).return_type ());
1324
1343
dest.add (goto_programt::make_assignment (
@@ -1333,7 +1352,7 @@ void goto_convertt::do_function_call_symbol(
1333
1352
throw 0 ;
1334
1353
}
1335
1354
1336
- exprt dest_expr = make_va_list (arguments[0 ]);
1355
+ exprt dest_expr = make_va_list (arguments[0 ], ns );
1337
1356
const typecast_exprt src_expr (arguments[1 ], dest_expr.type ());
1338
1357
1339
1358
if (!is_assignable (dest_expr))
@@ -1357,7 +1376,7 @@ void goto_convertt::do_function_call_symbol(
1357
1376
throw 0 ;
1358
1377
}
1359
1378
1360
- exprt dest_expr = make_va_list (arguments[0 ]);
1379
+ exprt dest_expr = make_va_list (arguments[0 ], ns );
1361
1380
1362
1381
if (!is_assignable (dest_expr))
1363
1382
{
@@ -1392,7 +1411,7 @@ void goto_convertt::do_function_call_symbol(
1392
1411
throw 0 ;
1393
1412
}
1394
1413
1395
- exprt dest_expr = make_va_list (arguments[0 ]);
1414
+ exprt dest_expr = make_va_list (arguments[0 ], ns );
1396
1415
1397
1416
if (!is_assignable (dest_expr))
1398
1417
{
0 commit comments