Skip to content

Commit 9ca6bf3

Browse files
authored
[LoongArch] Fix ABI mismatch with gcc/g++ about empty structs passing (#70320)
How empty structs (not as fields of container struct) are passed in C++ is not explicitly documented in psABI. However, this patch fixes the mismatch with g++. Note that the unnamed bitfield case `struct { int : 1; }` in C is also fixed. Previously clang regards it as an empty struct and then ignores it when passing. Now size of the struct is counted; since it's size is not 0, clang will not ignore it even in C. While https://reviews.llvm.org/D156116 fixed the handling of empty struct when considering eligibility of the container struct for the FP calling convention ('flattening'), this patch fixes the handling of passing the empty struct itself. Fix #70319
1 parent 562ce8b commit 9ca6bf3

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

clang/lib/CodeGen/Targets/LoongArch.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,14 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
308308
CGCXXABI::RAA_DirectInMemory);
309309
}
310310

311-
// Ignore empty structs/unions.
312-
if (isEmptyRecord(getContext(), Ty, true))
313-
return ABIArgInfo::getIgnore();
314-
315311
uint64_t Size = getContext().getTypeSize(Ty);
316312

313+
// Ignore empty struct or union whose size is zero, e.g. `struct { }` in C or
314+
// `struct { int a[0]; }` in C++. In C++, `struct { }` is empty but it's size
315+
// is 1 byte and g++ doesn't ignore it; clang++ matches this behaviour.
316+
if (isEmptyRecord(getContext(), Ty, true) && Size == 0)
317+
return ABIArgInfo::getIgnore();
318+
317319
// Pass floating point values via FARs if possible.
318320
if (IsFixed && Ty->isFloatingType() && !Ty->isComplexType() &&
319321
FRLen >= Size && FARsLeft) {

clang/test/CodeGen/LoongArch/abi-lp64d-empty-structs.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ struct s9 test_s9(struct s9 a) {
9393
}
9494

9595
// CHECK-C: define{{.*}} void @test_s10()
96-
// CHECK-CXX: define{{.*}} void @_Z8test_s103s10()
96+
// CHECK-CXX: define{{.*}} i64 @_Z8test_s103s10(i64 {{.*}})
9797
struct s10 { };
9898
struct s10 test_s10(struct s10 a) {
9999
return a;
@@ -128,14 +128,14 @@ struct s14 test_s14(struct s14 a) {
128128
}
129129

130130
// CHECK-C: define{{.*}} void @test_s15()
131-
// CHECK-CXX: define{{.*}} void @_Z8test_s153s15()
131+
// CHECK-CXX: define{{.*}} i64 @_Z8test_s153s15(i64 {{.*}})
132132
struct s15 { int : 0; };
133133
struct s15 test_s15(struct s15 a) {
134134
return a;
135135
}
136136

137-
// CHECK-C: define{{.*}} void @test_s16()
138-
// CHECK-CXX: define{{.*}} void @_Z8test_s163s16()
137+
// CHECK-C: define{{.*}} i64 @test_s16(i64 {{.*}})
138+
// CHECK-CXX: define{{.*}} i64 @_Z8test_s163s16(i64 {{.*}})
139139
struct s16 { int : 1; };
140140
struct s16 test_s16(struct s16 a) {
141141
return a;

0 commit comments

Comments
 (0)