Skip to content

Commit 956b47b

Browse files
authored
[X86_32] Teach X86_32 va_arg to ignore empty structs. (#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.
1 parent 1f26809 commit 956b47b

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

clang/lib/CodeGen/Targets/X86.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,
10691069

10701070
auto TypeInfo = getContext().getTypeInfoInChars(Ty);
10711071

1072+
CCState State(*const_cast<CGFunctionInfo *>(CGF.CurFnInfo));
1073+
ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
1074+
// Empty records are ignored for parameter passing purposes.
1075+
if (AI.isIgnore())
1076+
return CGF.CreateMemTemp(Ty);
1077+
10721078
// x86-32 changes the alignment of certain arguments on the stack.
10731079
//
10741080
// Just messing with TypeInfo like this works because we never pass
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2+
// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
3+
4+
typedef struct {} empty;
5+
6+
// CHECK-LABEL: @_Z17empty_record_testiz(
7+
// CHECK-NEXT: entry:
8+
// CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4
9+
// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4
10+
// CHECK-NEXT: [[LIST:%.*]] = alloca ptr, align 4
11+
// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
12+
// CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
13+
// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
14+
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[LIST]])
15+
// CHECK-NEXT: ret void
16+
//
17+
empty empty_record_test(int z, ...) {
18+
__builtin_va_list list;
19+
__builtin_va_start(list, z);
20+
return __builtin_va_arg(list, empty);
21+
}

0 commit comments

Comments
 (0)