https://github.com/CoTinker created https://github.com/llvm/llvm-project/pull/86075
Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. Fix #86057. >From 944259ba90fc13c04b6bbd44ec1737fbbb56b2d1 Mon Sep 17 00:00:00 2001 From: Longsheng Mou <moulongsh...@huawei.com> Date: Thu, 21 Mar 2024 11:23:56 +0800 Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs. Empty structs are ignored for parameter passing purposes, but va_arg was incrementing the pointer anyway for that the size of empty struct in c++ is 1 byte, which could lead to va_list getting out of sync. --- clang/lib/CodeGen/Targets/X86.cpp | 4 ++++ clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 1ec0f159ebcb8a..7931f56ad6835f 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -1069,6 +1069,10 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF, auto TypeInfo = getContext().getTypeInfoInChars(Ty); + // Empty records are ignored for parameter passing purposes on non-Windows. + if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true)) + return CGF.CreateMemTemp(Ty); + // x86-32 changes the alignment of certain arguments on the stack. // // Just messing with TypeInfo like this works because we never pass diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp b/clang/test/CodeGenCXX/x86_32-vaarg.cpp new file mode 100644 index 00000000000000..23eac1164118c6 --- /dev/null +++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp @@ -0,0 +1,20 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s + +typedef struct {} empty; + +// CHECK-LABEL: @{{.*}}empty_record_test +// CHECK-NEXT: entry: +// CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[LIST:%.*]] = alloca ptr, align 4 +// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1 +// CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 +// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 +// CHECK-NEXT: call void @llvm.va_start(ptr [[LIST]]) +empty empty_record_test(int z, ...) { + __builtin_va_list list; + __builtin_va_start(list, z); + return __builtin_va_arg(list, empty); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits