225 lines · plain
1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -Wconversion -verify -o - %s -DERROR=12// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -Wno-conversion -ast-dump %s | FileCheck %s3 4// This test verifies floating point type implicit conversion ranks for overload5// resolution. In HLSL the built-in type ranks are half < float < double. This6// applies to both scalar and vector types.7 8// HLSL allows implicit truncation fo types, so it differentiates between9// promotions (converting to larger types) and conversions (converting to10// smaller types). Promotions are preferred over conversions. Promotions prefer11// promoting to the next lowest type in the ranking order. Conversions prefer12// 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 exact50// match.51// (b) When called with float it will resolve to float because float is an52// exact match.53// (c) When called with double it will resolve to double because it is an54// 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 an77// exact match.78// (c) When called with double it will resolve to double because it is an79// exact match.80 81// CHECK-LABEL: FunctionDecl {{.*}} Case2 'void (half2, float2, double2)'82void Case2(half2 H, float2 F, double2 D) {83#if ERROR84 FloatDouble(H); // expected-error {{call to 'FloatDouble' is ambiguous}}85#endif86 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 overloads99// (a) When called with half, it will resolve to half because it is an exact100// match.101// (b) When called with flaot, it will resolve to double because double is a102// valid promotion.103// (c) When called with double, it will resolve to double because it is an104// 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 exact126// match.127// (b) When called with float it will resolve to float because float is an128// 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 ERROR144 HalfFloat(D); // expected-error{{call to 'HalfFloat' is ambiguous}}145#endif146}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 a150// valid promotion.151// (b) When called with float it will resolve to double because double is a152// valid promotion.153// (c) When called with double it will resolve to double because it is an154// 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 a176// valid promotion.177// (b) When called with float it will resolve to float because float is an178// exact match.179// (c) When called with double it will resolve to float because it is a180// 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 an202// exact match203// (b) When called with float it will resolve to half because half is a204// valid conversion.205// (c) When called with double it will resolve to float because it is a206// 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