[clang] fix: C++ empty record with align lead to va_list out of sync (PR #72197)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 9 09:25:20 PDT 2025
https://github.com/hstk30-hw updated https://github.com/llvm/llvm-project/pull/72197
>From f7104c0d2623f6c69ed2361b22739e629cfd9755 Mon Sep 17 00:00:00 2001
From: hstk30 <hanwei62 at huawei.com>
Date: Fri, 10 Oct 2025 00:17:09 +0800
Subject: [PATCH] fix: C++ empty record with align break aarch64 AAPCS64
---
clang/lib/CodeGen/Targets/AArch64.cpp | 9 ++++++---
clang/test/CodeGen/arm64-microsoft-arguments.cpp | 4 ++--
clang/test/CodeGenCXX/aarch64-arguments.cpp | 2 +-
clang/test/CodeGenCXX/arm64-darwinpcs.cpp | 2 +-
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp
index d7deece232a9f..9adace69c06c6 100644
--- a/clang/lib/CodeGen/Targets/AArch64.cpp
+++ b/clang/lib/CodeGen/Targets/AArch64.cpp
@@ -422,6 +422,12 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
}
// Empty records:
+ // AAPCS64 does not say that empty records are ignored as arguments,
+ // but other compilers do so in certain situations, and we copy that behavior.
+ // Those situations are in fact language-mode-specific, which seems really
+ // unfortunate, but it's something we just have to accept. If this doesn't
+ // apply, just fall through to the standard argument-handling path.
+ // Darwin overrides the psABI here to ignore all empty records in all modes.
uint64_t Size = getContext().getTypeSize(Ty);
bool IsEmpty = isEmptyRecord(getContext(), Ty, true);
if (!Ty->isSVESizelessBuiltinType() && (IsEmpty || Size == 0)) {
@@ -434,9 +440,6 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn,
// behaviour here.
if (Size == 0)
return ABIArgInfo::getIgnore();
-
- // Otherwise, they are passed as if they have a size of 1 byte.
- return ABIArgInfo::getDirect(llvm::Type::getInt8Ty(getVMContext()));
}
// Homogeneous Floating-point Aggregates (HFAs) need to be expanded.
diff --git a/clang/test/CodeGen/arm64-microsoft-arguments.cpp b/clang/test/CodeGen/arm64-microsoft-arguments.cpp
index a0a81be54325f..b771af83b6da0 100644
--- a/clang/test/CodeGen/arm64-microsoft-arguments.cpp
+++ b/clang/test/CodeGen/arm64-microsoft-arguments.cpp
@@ -57,7 +57,7 @@ S4 f4() {
// Pass and return from instance method called from instance method.
// CHECK: define {{.*}} void @{{.*}}bar at Q1{{.*}}(ptr {{[^,]*}} %this, ptr dead_on_unwind inreg noalias writable sret(%class.P1) align 1 %agg.result)
-// CHECK: call void {{.*}}foo at P1{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P1) align 1 %agg.result, i8 %0)
+// CHECK: call void {{.*}}foo at P1{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P1) align 1 %agg.result, i64 %0)
class P1 {
public:
@@ -76,7 +76,7 @@ P1 Q1::bar() {
// Pass and return from instance method called from free function.
// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
-// CHECK: call void {{.*}}foo at P2{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P2) align 1 %retval, i8 %0)
+// CHECK: call void {{.*}}foo at P2{{.*}}(ptr noundef{{[^,]*}} %ref.tmp, ptr dead_on_unwind inreg writable sret(%class.P2) align 1 %retval, i64 %0)
class P2 {
public:
P2 foo(P2 x);
diff --git a/clang/test/CodeGenCXX/aarch64-arguments.cpp b/clang/test/CodeGenCXX/aarch64-arguments.cpp
index ffb0cafa8882d..3206e38ad0090 100644
--- a/clang/test/CodeGenCXX/aarch64-arguments.cpp
+++ b/clang/test/CodeGenCXX/aarch64-arguments.cpp
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -triple arm64-none-linux -emit-llvm -w -o - %s | FileCheck -check-prefix=PCS %s
-// PCS: define{{.*}} void @{{.*}}(i8 %a
+// PCS: define{{.*}} void @{{.*}}(i64 %a.coerce)
struct s0 {};
void f0(s0 a) {}
diff --git a/clang/test/CodeGenCXX/arm64-darwinpcs.cpp b/clang/test/CodeGenCXX/arm64-darwinpcs.cpp
index a0b0d9efdd4c4..ef0e2da3effac 100644
--- a/clang/test/CodeGenCXX/arm64-darwinpcs.cpp
+++ b/clang/test/CodeGenCXX/arm64-darwinpcs.cpp
@@ -7,7 +7,7 @@ void test_extensions(bool a, char b, short c) {}
struct Empty {};
void test_empty(Empty e) {}
-// CHECK: define{{.*}} void @_Z10test_empty5Empty(i8
+// CHECK: define{{.*}} void @_Z10test_empty5Empty(i64 %e.coerce)
// CHECK-DARWIN: define{{.*}} void @_Z10test_empty5Empty()
struct HFA {
More information about the cfe-commits
mailing list