1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -fsyntax-only %s -DERROR=1 -verify 2// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -ast-dump %s | FileCheck %s 3 4 5// Case 1: Prioritize splat without conversion over conversion. In this case the 6// called functions have valid overloads for each type, however one of the 7// overloads is a vector rather than scalar. Each call should resolve to the 8// same type, and the vector should splat. 9void HalfFloatDoubleV(double2 D); 10void HalfFloatDoubleV(float F); 11void HalfFloatDoubleV(half H); 12 13void HalfFloatVDouble(double D); 14void HalfFloatVDouble(float2 F); 15void HalfFloatVDouble(half H); 16 17void HalfVFloatDouble(double D); 18void HalfVFloatDouble(float F); 19void HalfVFloatDouble(half2 H); 20 21 22// CHECK-LABEL: FunctionDecl {{.*}} Case1 'void (half, float, double)' 23void Case1(half H, float F, double D) { 24 // CHECK: CallExpr {{.*}} 'void' 25 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay> 26 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'HalfFloatDoubleV' 'void (half)' 27 HalfFloatDoubleV(H); 28 29 // CHECK: CallExpr {{.*}} 'void' 30 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay> 31 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'HalfFloatDoubleV' 'void (float)' 32 HalfFloatDoubleV(F); 33 34 // CHECK: CallExpr {{.*}} 'void' 35 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 36 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfFloatDoubleV' 'void (double2)' 37 HalfFloatDoubleV(D); 38 39 // CHECK: CallExpr {{.*}} 'void' 40 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay> 41 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'HalfFloatVDouble' 'void (half)' 42 HalfFloatVDouble(H); 43 44 // CHECK: CallExpr {{.*}} 'void' 45 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 46 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'HalfFloatVDouble' 'void (float2)' 47 HalfFloatVDouble(F); 48 49 // CHECK: CallExpr {{.*}} 'void' 50 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay> 51 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'HalfFloatVDouble' 'void (double)' 52 HalfFloatVDouble(D); 53 54 // CHECK: CallExpr {{.*}} 'void' 55 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 56 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfVFloatDouble' 'void (half2)' 57 HalfVFloatDouble(H); 58 59 // CHECK: CallExpr {{.*}} 'void' 60 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay> 61 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'HalfVFloatDouble' 'void (float)' 62 HalfVFloatDouble(F); 63 64 // CHECK: CallExpr {{.*}} 'void' 65 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay> 66 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'HalfVFloatDouble' 'void (double)' 67 HalfVFloatDouble(D); 68} 69 70// Case 2: Prefer splat+promotion over conversion. In this case the overloads 71// require a splat+promotion or a conversion. The call will resolve to the 72// splat+promotion. 73void HalfDoubleV(double2 D); 74void HalfDoubleV(half H); 75 76// CHECK-LABEL: FunctionDecl {{.*}} Case2 'void (float)' 77void Case2(float F) { 78 // CHECK: CallExpr {{.*}} 'void' 79 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 80 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfDoubleV' 'void (double2)' 81 HalfDoubleV(F); 82} 83 84// Case 3: Prefer promotion or conversion without splat over the splat. In this 85// case the scalar value will overload to the scalar function. 86void DoubleV(double D); 87void DoubleV(double2 V); 88 89void HalfV(half D); 90void HalfV(half2 V); 91 92// CHECK-LABEL: FunctionDecl {{.*}} Case3 'void (float)' 93void Case3(float F) { 94 // CHECK: CallExpr {{.*}} 'void' 95 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay> 96 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'DoubleV' 'void (double)' 97 DoubleV(F); 98 99 // CHECK: CallExpr {{.*}} 'void' 100 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay> 101 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'HalfV' 'void (half)' 102 HalfV(F); 103} 104 105#if ERROR 106// Case 4: It is ambiguous to resolve two splat+conversion or splat+promotion 107// functions. In all the calls below an error occurs. 108void FloatVDoubleV(float2 F); // expected-note {{candidate function}} 109void FloatVDoubleV(double2 D); // expected-note {{candidate function}} 110 111void HalfVFloatV(half2 H); // expected-note {{candidate function}} 112void HalfVFloatV(float2 F); // expected-note {{candidate function}} 113 114void Case4(half H, double D) { 115 FloatVDoubleV(H); // expected-error {{call to 'FloatVDoubleV' is ambiguous}} 116 117 HalfVFloatV(D); // expected-error {{call to 'HalfVFloatV' is ambiguous}} 118} 119 120// Case 5: It is ambiguous to resolve two splats of different lengths. 121void FloatV(float2 V); // expected-note {{candidate function}} expected-note {{candidate function}} expected-note {{candidate function}} 122void FloatV(float4 V); // expected-note {{candidate function}} expected-note {{candidate function}} expected-note {{candidate function}} 123 124void Case5(half H, float F, double D) { 125 FloatV(H); // expected-error {{call to 'FloatV' is ambiguous}} 126 FloatV(F); // expected-error {{call to 'FloatV' is ambiguous}} 127 FloatV(D); // expected-error {{call to 'FloatV' is ambiguous}} 128} 129#endif 130 131// Case 5: Vectors truncate or match, but don't extend. 132void FloatV24(float2 V); 133void FloatV24(float4 V); 134 135// CHECK-LABEL: FunctionDecl {{.*}} Case5 'void (half3, float3, double3, half4, float4, double4)' 136void Case5(half3 H3, float3 F3, double3 D3, half4 H4, float4 F4, double4 D4) { 137 // CHECK: CallExpr {{.*}} 'void' 138 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 139 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'FloatV24' 'void (float2)' 140 FloatV24(H3); // expected-warning{{implicit conversion truncates vector: 'half3' (aka 'vector<half, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} 141 142 // CHECK: CallExpr {{.*}} 'void' 143 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 144 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'FloatV24' 'void (float2)' 145 FloatV24(F3); // expected-warning{{implicit conversion truncates vector: 'float3' (aka 'vector<float, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} 146 147 // CHECK: CallExpr {{.*}} 'void' 148 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 149 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'FloatV24' 'void (float2)' 150 FloatV24(D3); // expected-warning{{implicit conversion truncates vector: 'double3' (aka 'vector<double, 3>') to 'vector<float, 2>' (vector of 2 'float' values)}} 151 152 // CHECK: CallExpr {{.*}} 'void' 153 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float4)' <FunctionToPointerDecay> 154 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float4)' lvalue Function {{.*}} 'FloatV24' 'void (float4)' 155 FloatV24(H4); 156 157 // CHECK: CallExpr {{.*}} 'void' 158 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float4)' <FunctionToPointerDecay> 159 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float4)' lvalue Function {{.*}} 'FloatV24' 'void (float4)' 160 FloatV24(F4); 161 162 // CHECK: CallExpr {{.*}} 'void' 163 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float4)' <FunctionToPointerDecay> 164 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float4)' lvalue Function {{.*}} 'FloatV24' 'void (float4)' 165 FloatV24(D4); 166} 167