diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5997,6 +5997,16 @@ CodeGenFunction &CGF) const { ABIArgInfo AI = classifyArgumentType(Ty, /*IsVariadic=*/true, CGF.CurFnInfo->getCallingConvention()); + // Empty records are ignored for parameter passing purposes. + if (AI.isIgnore()) { + uint64_t PointerSize = getTarget().getPointerWidth(0) / 8; + CharUnits SlotSize = CharUnits::fromQuantity(PointerSize); + VAListAddr = CGF.Builder.CreateElementBitCast(VAListAddr, CGF.Int8PtrTy); + auto *Load = CGF.Builder.CreateLoad(VAListAddr); + Address Addr = Address(Load, CGF.Int8Ty, SlotSize); + return CGF.Builder.CreateElementBitCast(Addr, CGF.ConvertTypeForMem(Ty)); + } + bool IsIndirect = AI.isIndirect(); llvm::Type *BaseTy = CGF.ConvertType(Ty); diff --git a/clang/test/CodeGen/aarch64-varargs.c b/clang/test/CodeGen/aarch64-varargs.c --- a/clang/test/CodeGen/aarch64-varargs.c +++ b/clang/test/CodeGen/aarch64-varargs.c @@ -894,4 +894,10 @@ // CHECK: call void @llvm.va_start(i8* [[VOIDP_THE_LIST]]) } - +typedef struct {} empty; +empty empty_record_test(void) { +// CHECK-LABEL: define{{.*}} void @empty_record_test() + return va_arg(the_list, empty); +// CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i8*, i8** getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 0) +// CHECK: [[ADDR:%[a-z._0-9]+]] = bitcast i8* [[GR_OFFS]] to %struct.empty* +}