diff --git a/c-tests/new/issue361.c b/c-tests/new/issue361.c new file mode 100644 index 0000000000..74add2b0c6 --- /dev/null +++ b/c-tests/new/issue361.c @@ -0,0 +1,17 @@ +#include +struct car { + char a; + long d; +}; + +o (int n, ...) { + struct car c0, c; + va_list args; + va_arg (args, struct car); + int n0; + c = va_arg (args, struct car); + int n2 = (args); + return 0; +} + +int main (void) { return 0; } diff --git a/c2mir/c2mir.c b/c2mir/c2mir.c index 8949073c0d..dd26b5a025 100644 --- a/c2mir/c2mir.c +++ b/c2mir/c2mir.c @@ -12204,14 +12204,20 @@ static op_t gen (c2m_ctx_t c2m_ctx, node_t r, MIR_label_t true_label, MIR_label_ op2 = mem_to_address (c2m_ctx, op2, FALSE); } if (type->mode == TM_STRUCT || type->mode == TM_UNION) { - assert (desirable_dest != NULL && desirable_dest->mir_op.mode == MIR_OP_MEM); - res = mem_to_address (c2m_ctx, *desirable_dest, TRUE); + if (desirable_dest == NULL) { + res = get_new_temp (c2m_ctx, MIR_T_I64); + MIR_append_insn (ctx, curr_func, + MIR_new_insn (ctx, MIR_MOV, res.mir_op, MIR_new_int_op (ctx, 0))); + } else { + assert (desirable_dest->mir_op.mode == MIR_OP_MEM); + res = mem_to_address (c2m_ctx, *desirable_dest, TRUE); + } MIR_append_insn (ctx, curr_func, MIR_new_insn (ctx, MIR_VA_BLOCK_ARG, res.mir_op, op2.mir_op, MIR_new_int_op (ctx, type_size (c2m_ctx, type)), MIR_new_int_op (ctx, target_get_blk_type (c2m_ctx, type) - MIR_T_BLK))); - res = *desirable_dest; + if (desirable_dest != NULL) res = *desirable_dest; } else { MIR_append_insn (ctx, curr_func, MIR_new_insn (ctx, MIR_VA_ARG, op1.mir_op, op2.mir_op, diff --git a/mir-aarch64.c b/mir-aarch64.c index a937259895..bbac2aed59 100644 --- a/mir-aarch64.c +++ b/mir-aarch64.c @@ -108,7 +108,7 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { a = *(void **) a; va->arg_area++; } - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); #else void *a; long size = (s + 7) / 8 * 8; @@ -117,7 +117,7 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { a = va->__stack; va->__stack = (char *) va->__stack + size; va->__gr_offs += size; - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); return; } if (size > 2 * 8) size = 8; @@ -129,7 +129,7 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { va->__stack = (char *) va->__stack + size; } if (s > 2 * 8) a = *(void **) a; /* address */ - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); #endif } diff --git a/mir-ppc64.c b/mir-ppc64.c index b601686d11..a9247fdd4b 100644 --- a/mir-ppc64.c +++ b/mir-ppc64.c @@ -243,7 +243,7 @@ void *va_arg_builtin (void *p, uint64_t t) { void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { struct ppc64_va_list *va = p; void *a = va->arg_area; - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); va->arg_area += (s + sizeof (uint64_t) - 1) / sizeof (uint64_t); } diff --git a/mir-riscv64.c b/mir-riscv64.c index df328bd8a5..c637e2a3e6 100644 --- a/mir-riscv64.c +++ b/mir-riscv64.c @@ -101,7 +101,7 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { a = *(void **) a; va->arg_area++; } - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); } void va_start_interp_builtin (MIR_context_t ctx, void *p, void *a) { diff --git a/mir-s390x.c b/mir-s390x.c index 6230cfaf5c..192d398a5d 100644 --- a/mir-s390x.c +++ b/mir-s390x.c @@ -227,7 +227,8 @@ void *va_arg_builtin (void *p, uint64_t t) { } void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { - memcpy (res, *(void **) va_arg_builtin (p, MIR_T_I64), s); + void *a = *(void **) va_arg_builtin (p, MIR_T_I64); + if (res == NULL) memcpy (res, a, s); } void va_start_interp_builtin (MIR_context_t ctx, void *p, void *a) { diff --git a/mir-x86_64.c b/mir-x86_64.c index 86664ec0d0..bb22b70d37 100644 --- a/mir-x86_64.c +++ b/mir-x86_64.c @@ -79,7 +79,7 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { u[1].i = *(uint64_t *) ((char *) va->reg_save_area + va->gp_offset); va->gp_offset += 8; } - memcpy (res, &u, s); + if (res != NULL) memcpy (res, &u, s); return; case 2: u[0].d = *(double *) ((char *) va->reg_save_area + va->fp_offset); @@ -88,7 +88,7 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { u[1].d = *(double *) ((char *) va->reg_save_area + va->fp_offset); va->fp_offset += 16; } - memcpy (res, &u, s); + if (res != NULL) memcpy (res, &u, s); return; case 3: case 4: @@ -102,11 +102,11 @@ void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { } va->fp_offset += 8; va->gp_offset += 8; - memcpy (res, &u, s); + if (res != NULL) memcpy (res, &u, s); return; default: break; } - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); va->overflow_arg_area += size / 8; } @@ -134,7 +134,7 @@ void *va_arg_builtin (void *p, uint64_t t) { void va_block_arg_builtin (void *res, void *p, size_t s, uint64_t ncase) { struct x86_64_va_list *va = p; void *a = s <= 8 ? va->arg_area : *(void **) va->arg_area; /* pass by pointer */ - memcpy (res, a, s); + if (res != NULL) memcpy (res, a, s); va->arg_area++; }