| // RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++11 -emit-llvm \ |
| // RUN: -o - %s | FileCheck %s |
| // RUN: %clang_cc1 -triple arm64ec-pc-windows-msvc -std=c++11 -emit-llvm \ |
| // RUN: -o - %s | FileCheck %s |
| |
| enum class U8 : unsigned char {}; |
| enum class S8 : signed char {}; |
| enum class U16 : unsigned short {}; |
| enum class S16 : short {}; |
| enum class U32 : unsigned int {}; |
| enum ClassicU8 : unsigned char {}; |
| |
| extern "C" void variadic(int, ...); |
| |
| // Fixed parameters should continue to be passed without extension. |
| // CHECK-LABEL: define dso_local void @fixed(i8 noundef %{{[^)]+}}) |
| extern "C" void fixed(U8) {} |
| |
| // Named parameters of variadic functions are still fixed arguments. |
| // CHECK-LABEL: define dso_local void @named_variadic(i8 noundef %{{[^,]+}}, ...) |
| extern "C" void named_variadic(U8, ...) {} |
| |
| // CHECK-LABEL: define dso_local void @test( |
| // CHECK: call void (i32, ...) @variadic( |
| // CHECK-SAME: i32 noundef 0, |
| // Scoped enums do not undergo the default argument integer promotions, so they |
| // retain their i8/i16 IR types and use extension attributes for ABI widening. |
| // CHECK-SAME: i8 noundef zeroext %{{[^,]+}}, i8 noundef signext %{{[^,]+}}, |
| // CHECK-SAME: i16 noundef zeroext %{{[^,]+}}, i16 noundef signext %{{[^,]+}}, |
| // Regular integer types and unscoped enums do undergo integer promotion (for |
| // example, unsigned char to int), so those arguments are passed as i32. |
| // CHECK-SAME: i32 noundef %{{[^,]+}}, i32 noundef %{{[^,]+}}, i32 noundef %{{[^)]+}}) |
| extern "C" void test(U8 u8, S8 s8, U16 u16, S16 s16, U32 u32, |
| ClassicU8 classic_u8, unsigned char plain_u8) { |
| variadic(0, u8, s8, u16, s16, u32, classic_u8, plain_u8); |
| } |