167 lines · plain
1// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -fsyntax-only %s -DERROR=1 -verify2// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -ast-dump %s | FileCheck %s3 4 5// Case 1: Prioritize splat without conversion over conversion. In this case the6// called functions have valid overloads for each type, however one of the7// overloads is a vector rather than scalar. Each call should resolve to the8// 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 overloads71// require a splat+promotion or a conversion. The call will resolve to the72// 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 this85// 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 ERROR106// Case 4: It is ambiguous to resolve two splat+conversion or splat+promotion107// 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#endif130 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