Skip to content

Commit 944259b

Browse files
committed
[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.
1 parent 44a81af commit 944259b

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

clang/lib/CodeGen/Targets/X86.cpp

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

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

1072+
// Empty records are ignored for parameter passing purposes on non-Windows.
1073+
if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true))
1074+
return CGF.CreateMemTemp(Ty);
1075+
10721076
// x86-32 changes the alignment of certain arguments on the stack.
10731077
//
10741078
// Just messing with TypeInfo like this works because we never pass
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck %s
4+
5+
typedef struct {} empty;
6+
7+
// CHECK-LABEL: @{{.*}}empty_record_test
8+
// CHECK-NEXT: entry:
9+
// CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4
10+
// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4
11+
// CHECK-NEXT: [[LIST:%.*]] = alloca ptr, align 4
12+
// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
13+
// CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
14+
// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
15+
// CHECK-NEXT: call void @llvm.va_start(ptr [[LIST]])
16+
empty empty_record_test(int z, ...) {
17+
__builtin_va_list list;
18+
__builtin_va_start(list, z);
19+
return __builtin_va_arg(list, empty);
20+
}

0 commit comments

Comments
 (0)