[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 15 04:26:35 PST 2024


https://github.com/hstk30-hw updated https://github.com/llvm/llvm-project/pull/77907

>From 2f4290732804588d7c8f0de07836cfd5976085b8 Mon Sep 17 00:00:00 2001
From: Longsheng Mou <moulongsheng at huawei.com>
Date: Fri, 12 Jan 2024 18:24:08 +0800
Subject: [PATCH] [X86_64] fix empty structure vaarg in c++

SizeInBytes of empty structure is 0 in C, while 1 in C++.
And empty structure argument of the function is ignored
in X86_64 backend.As a result, the value of variable
arguments in C++ is incorrect.
---
 clang/lib/CodeGen/Targets/X86.cpp      |  5 ++++-
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 16 ++++++++++++++++
 2 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CodeGenCXX/x86_64-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index d053f41ab168f5e..79b8306588277e8 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2988,7 +2988,10 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction &CGF,
   // AMD64-ABI 3.5.7p5: Step 10. Align l->overflow_arg_area upwards to
   // an 8 byte boundary.
 
-  uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
+  uint64_t SizeInBytes = 0;
+  if (!isEmptyRecord(CGF.getContext(), Ty, true, true))
+    SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
+
   llvm::Value *Offset =
       llvm::ConstantInt::get(CGF.Int32Ty, (SizeInBytes + 7)  & ~7);
   overflow_arg_area = CGF.Builder.CreateGEP(CGF.Int8Ty, overflow_arg_area,
diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
new file mode 100644
index 000000000000000..9c1af37fe429545
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
@@ -0,0 +1,16 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+struct Empty { struct { struct { } e; }; };
+
+struct Empty emptyvar;
+
+void take_args(int a, ...) {
+// CHECK:      %overflow_arg_area = load ptr, ptr %overflow_arg_area_p, align 8
+// CHECK-NEXT: %overflow_arg_area.next = getelementptr i8, ptr %overflow_arg_area, i32 0
+// CHECK-NEXT: store ptr %overflow_arg_area.next, ptr %overflow_arg_area_p, align 8
+  __builtin_va_list l;
+  __builtin_va_start(l, a);
+  emptyvar = __builtin_va_arg(l, struct Empty);
+  __builtin_va_end(l);
+}



More information about the cfe-commits mailing list