Skip to content

Commit

Permalink
[X86_32] Teach X86_32 va_arg to ignore empty structs. (#86075)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
CoTinker committed Apr 3, 2024
1 parent 1f26809 commit 956b47b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 0 deletions.
6 changes: 6 additions & 0 deletions clang/lib/CodeGen/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,

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

CCState State(*const_cast<CGFunctionInfo *>(CGF.CurFnInfo));
ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
// Empty records are ignored for parameter passing purposes.
if (AI.isIgnore())
return CGF.CreateMemTemp(Ty);

// x86-32 changes the alignment of certain arguments on the stack.
//
// Just messing with TypeInfo like this works because we never pass
Expand Down
21 changes: 21 additions & 0 deletions clang/test/CodeGenCXX/x86_32-vaarg.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s

typedef struct {} empty;

// CHECK-LABEL: @_Z17empty_record_testiz(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[LIST:%.*]] = alloca ptr, align 4
// CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
// CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
// CHECK-NEXT: call void @llvm.va_start.p0(ptr [[LIST]])
// CHECK-NEXT: ret void
//
empty empty_record_test(int z, ...) {
__builtin_va_list list;
__builtin_va_start(list, z);
return __builtin_va_arg(list, empty);
}

0 comments on commit 956b47b

Please sign in to comment.