xref: /llvm-project/clang/test/SemaHLSL/SplatOverloadResolution.hlsl (revision d91ff3f2409a721b61b68c6a8438ea6c59323df8)
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