1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -Wconversion -verify -o - %s -DERROR=1 2// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -Wno-conversion -ast-dump %s | FileCheck %s 3 4// This test verifies floating point type implicit conversion ranks for overload 5// resolution. In HLSL the built-in type ranks are half < float < double. This 6// applies to both scalar and vector types. 7 8// HLSL allows implicit truncation fo types, so it differentiates between 9// promotions (converting to larger types) and conversions (converting to 10// smaller types). Promotions are preferred over conversions. Promotions prefer 11// promoting to the next lowest type in the ranking order. Conversions prefer 12// converting to the next highest type in the ranking order. 13 14void HalfFloatDouble(double2 D); 15void HalfFloatDouble(float2 F); 16void HalfFloatDouble(half2 H); 17 18// CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (double2)' 19// CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (float2)' 20// CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (half2)' 21 22void FloatDouble(double2 D); // expected-note {{candidate function}} 23void FloatDouble(float2 F); // expected-note {{candidate function}} 24 25// CHECK: FunctionDecl {{.*}} used FloatDouble 'void (double2)' 26// CHECK: FunctionDecl {{.*}} used FloatDouble 'void (float2)' 27 28void HalfDouble(double2 D); 29void HalfDouble(half2 H); 30 31// CHECK: FunctionDecl {{.*}} used HalfDouble 'void (double2)' 32// CHECK: FunctionDecl {{.*}} used HalfDouble 'void (half2)' 33 34void HalfFloat(float2 F); // expected-note {{candidate function}} 35void HalfFloat(half2 H); // expected-note {{candidate function}} 36 37// CHECK: FunctionDecl {{.*}} used HalfFloat 'void (float2)' 38// CHECK: FunctionDecl {{.*}} used HalfFloat 'void (half2)' 39 40void Double(double2 D); 41void Float(float2 F); 42void Half(half2 H); 43 44// CHECK: FunctionDecl {{.*}} used Double 'void (double2)' 45// CHECK: FunctionDecl {{.*}} used Float 'void (float2)' 46// CHECK: FunctionDecl {{.*}} used Half 'void (half2)' 47 48// Case 1: A function declared with overloads for half float and double types. 49// (a) When called with half, it will resolve to half because half is an exact 50// match. 51// (b) When called with float it will resolve to float because float is an 52// exact match. 53// (c) When called with double it will resolve to double because it is an 54// exact match. 55 56// CHECK-LABEL: FunctionDecl {{.*}} Case1 'void (half2, float2, double2)' 57void Case1(half2 H, float2 F, double2 D) { 58 // CHECK: CallExpr {{.*}} 'void' 59 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 60 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (half2)' 61 HalfFloatDouble(H); 62 63 // CHECK: CallExpr {{.*}} 'void' 64 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 65 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (float2)' 66 HalfFloatDouble(F); 67 68 // CHECK: CallExpr {{.*}} 'void' 69 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 70 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (double2)' 71 HalfFloatDouble(D); 72} 73 74// Case 2: A function declared with double and float overlaods. 75// (a) When called with half, it fails to resulve the ambiguous promotion. 76// (b) When called with float it will resolve to float because float is an 77// exact match. 78// (c) When called with double it will resolve to double because it is an 79// exact match. 80 81// CHECK-LABEL: FunctionDecl {{.*}} Case2 'void (half2, float2, double2)' 82void Case2(half2 H, float2 F, double2 D) { 83#if ERROR 84 FloatDouble(H); // expected-error {{call to 'FloatDouble' is ambiguous}} 85#endif 86 87 // CHECK: CallExpr {{.*}} 'void' 88 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 89 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'FloatDouble' 'void (float2)' 90 FloatDouble(F); 91 92 // CHECK: CallExpr {{.*}} 'void' 93 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 94 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'FloatDouble' 'void (double2)' 95 FloatDouble(D); 96} 97 98// Case 3: A function declared with half and double overloads 99// (a) When called with half, it will resolve to half because it is an exact 100// match. 101// (b) When called with flaot, it will resolve to double because double is a 102// valid promotion. 103// (c) When called with double, it will resolve to double because it is an 104// exact match. 105 106// CHECK-LABEL: FunctionDecl {{.*}} Case3 'void (half2, float2, double2)' 107void Case3(half2 H, float2 F, double2 D) { 108 // CHECK: CallExpr {{.*}} 'void' 109 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 110 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfDouble' 'void (half2)' 111 HalfDouble(H); 112 113 // CHECK: CallExpr {{.*}} 'void' 114 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 115 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfDouble' 'void (double2)' 116 HalfDouble(F); 117 118 // CHECK: CallExpr {{.*}} 'void' 119 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 120 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'HalfDouble' 'void (double2)' 121 HalfDouble(D); 122} 123 124// Case 4: A function declared with half and float overloads. 125// (a) When called with half, it will resolve to half because half is an exact 126// match. 127// (b) When called with float it will resolve to float because float is an 128// exact match. 129// (c) When called with double it fails to resolve the ambigjuous conversion. 130 131// CHECK-LABEL: FunctionDecl {{.*}} Case4 'void (half2, float2, double2)' 132void Case4(half2 H, float2 F, double2 D) { 133 // CHECK: CallExpr {{.*}} 'void' 134 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 135 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'HalfFloat' 'void (half2)' 136 HalfFloat(H); 137 138 // CHECK: CallExpr {{.*}} 'void' 139 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 140 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'HalfFloat' 'void (float2)' 141 HalfFloat(F); 142 143#if ERROR 144 HalfFloat(D); // expected-error{{call to 'HalfFloat' is ambiguous}} 145#endif 146} 147 148// Case 5: A function declared with only a double overload. 149// (a) When called with half, it will resolve to double because double is a 150// valid promotion. 151// (b) When called with float it will resolve to double because double is a 152// valid promotion. 153// (c) When called with double it will resolve to double because it is an 154// exact match. 155 156// CHECK-LABEL: FunctionDecl {{.*}} Case5 'void (half2, float2, double2)' 157void Case5(half2 H, float2 F, double2 D) { 158 // CHECK: CallExpr {{.*}} 'void' 159 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 160 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'Double' 'void (double2)' 161 Double(H); 162 163 // CHECK: CallExpr {{.*}} 'void' 164 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 165 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'Double' 'void (double2)' 166 Double(F); 167 168 // CHECK: CallExpr {{.*}} 'void' 169 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double2)' <FunctionToPointerDecay> 170 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double2)' lvalue Function {{.*}} 'Double' 'void (double2)' 171 Double(D); 172} 173 174// Case 6: A function declared with only a float overload. 175// (a) When called with half, it will resolve to float because float is a 176// valid promotion. 177// (b) When called with float it will resolve to float because float is an 178// exact match. 179// (c) When called with double it will resolve to float because it is a 180// valid conversion. 181 182// CHECK-LABEL: FunctionDecl {{.*}} Case6 'void (half2, float2, double2)' 183void Case6(half2 H, float2 F, double2 D) { 184 // CHECK: CallExpr {{.*}} 'void' 185 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 186 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Float' 'void (float2)' 187 Float(H); 188 189 // CHECK: CallExpr {{.*}} 'void' 190 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 191 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Float' 'void (float2)' 192 Float(F); 193 194 // CHECK: CallExpr {{.*}} 'void' 195 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay> 196 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Float' 'void (float2)' 197 Float(D); // expected-warning{{implicit conversion loses floating-point precision: 'double2' (aka 'vector<double, 2>') to 'vector<float, 2>' (vector of 2 'float' values)}} 198} 199 200// Case 7: A function declared with only a half overload. 201// (a) When called with half, it will resolve to half because half is an 202// exact match 203// (b) When called with float it will resolve to half because half is a 204// valid conversion. 205// (c) When called with double it will resolve to float because it is a 206// valid conversion. 207 208// CHECK-LABEL: FunctionDecl {{.*}} Case7 'void (half2, float2, double2)' 209void Case7(half2 H, float2 F, double2 D) { 210 // CHECK: CallExpr {{.*}} 'void' 211 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 212 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'Half' 'void (half2)' 213 Half(H); 214 215 // CHECK: CallExpr {{.*}} 'void' 216 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 217 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'Half' 'void (half2)' 218 Half(F); // expected-warning{{implicit conversion loses floating-point precision: 'float2' (aka 'vector<float, 2>') to 'vector<half, 2>' (vector of 2 'half' values)}} 219 220 // CHECK: CallExpr {{.*}} 'void' 221 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half2)' <FunctionToPointerDecay> 222 // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half2)' lvalue Function {{.*}} 'Half' 'void (half2)' 223 Half(D); // expected-warning{{implicit conversion loses floating-point precision: 'double2' (aka 'vector<double, 2>') to 'vector<half, 2>' (vector of 2 'half' values)}} 224} 225