Skip to content

Commit 5178a00

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 5178a00

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-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: 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)