[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaHLSL / ScalarOverloadResolution.hlsl
blob77090b7fda2575b7c8db38b0e2d10ef7ff5da5ee
1 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -Wconversion -verify -o - -DERROR=1 %s
2 // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -fnative-half-type -finclude-default-header -ast-dump %s | FileCheck %s
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.
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.
14 void HalfFloatDouble(double D);
15 void HalfFloatDouble(float F);
16 void HalfFloatDouble(half H);
18 // CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (double)'
19 // CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (float)'
20 // CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (half)'
22 void FloatDouble(double D); // expected-note{{candidate function}}
23 void FloatDouble(float F); // expected-note{{candidate function}}
25 // CHECK: FunctionDecl {{.*}} used FloatDouble 'void (double)'
26 // CHECK: FunctionDecl {{.*}} used FloatDouble 'void (float)'
28 void HalfDouble(double D);
29 void HalfDouble(half H);
31 // CHECK: FunctionDecl {{.*}} used HalfDouble 'void (double)'
32 // CHECK: FunctionDecl {{.*}} used HalfDouble 'void (half)'
34 void HalfFloat(float F); // expected-note{{candidate function}}
35 void HalfFloat(half H); // expected-note{{candidate function}}
37 // CHECK: FunctionDecl {{.*}} used HalfFloat 'void (float)'
38 // CHECK: FunctionDecl {{.*}} used HalfFloat 'void (half)'
40 void Double(double D);
41 void Float(float F);
42 void Half(half H);
44 // CHECK: FunctionDecl {{.*}} used Double 'void (double)'
45 // CHECK: FunctionDecl {{.*}} used Float 'void (float)'
46 // CHECK: FunctionDecl {{.*}} used Half 'void (half)'
49 // Case 1: A function declared with overloads for half float and double types.
50 //   (a) When called with half, it will resolve to half because half is an exact
51 //   match.
52 //   (b) When called with float it will resolve to float because float is an
53 //   exact match.
54 //   (c) When called with double it will resolve to double because it is an
55 //   exact match.
57 // CHECK-LABEL: FunctionDecl {{.*}} Case1 'void (half, float, double)'
58 void Case1(half H, float F, double D) {
59   // CHECK: CallExpr {{.*}} 'void'
60   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay>
61   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (half)'
62   HalfFloatDouble(H);
64   // CHECK: CallExpr {{.*}} 'void'
65   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay>
66   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (float)'
67   HalfFloatDouble(F);
69   // CHECK: CallExpr {{.*}} 'void'
70   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
71   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'HalfFloatDouble' 'void (double)'
72   HalfFloatDouble(D);
75 // Case 2: A function declared with double and float overlaods.
76 //   (a) When called with half, it will fail to resolve because it cannot
77 //   disambiguate the promotions.
78 //   (b) When called with float it will resolve to float because float is an
79 //   exact match.
80 //   (c) When called with double it will resolve to double because it is an
81 //   exact match.
83 // CHECK-LABEL: FunctionDecl {{.*}} Case2 'void (half, float, double)'
84 void Case2(half H, float F, double D) {
85   #if ERROR
86   FloatDouble(H); // expected-error{{call to 'FloatDouble' is ambiguous}}
87   #endif
89   // CHECK: CallExpr {{.*}} 'void'
90   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay>
91   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'FloatDouble' 'void (float)'
92   FloatDouble(F);
94   // CHECK: CallExpr {{.*}} 'void'
95   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
96   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'FloatDouble' 'void (double)'
97   FloatDouble(D);
100 // Case 3: A function declared with half and double overloads
101 //   (a) When called with half, it will resolve to half because it is an exact
102 //   match.
103 //   (b) When called with flaot, it will resolve to double because double is a
104 //   valid promotion.
105 //   (c) When called with double, it will resolve to double because it is an
106 //   exact match.
108 // CHECK-LABEL: FunctionDecl {{.*}} Case3 'void (half, float, double)'
109 void Case3(half H, float F, double D) {
110   // CHECK: CallExpr {{.*}} 'void'
111   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay>
112   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'HalfDouble' 'void (half)'
113   HalfDouble(H);
115   // CHECK: CallExpr {{.*}} 'void'
116   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
117   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'HalfDouble' 'void (double)'
118   HalfDouble(F);
120   // CHECK: CallExpr {{.*}} 'void'
121   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
122   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'HalfDouble' 'void (double)'
123   HalfDouble(D);
126 // Case 4: A function declared with half and float overloads.
127 //   (a) When called with half, it will resolve to half because half is an exact
128 //   match.
129 //   (b) When called with float it will resolve to float because float is an
130 //   exact match.
131 //   (c) When called with double it will resolve to float because it is the
132 //   float is higher rank than half.
134 // CHECK-LABEL: FunctionDecl {{.*}} Case4 'void (half, float, double)'
135 void Case4(half H, float F, double D) {
136   // CHECK: CallExpr {{.*}} 'void'
137   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay>
138   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'HalfFloat' 'void (half)'
139   HalfFloat(H);
141   // CHECK: CallExpr {{.*}} 'void'
142   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay>
143   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'HalfFloat' 'void (float)'
144   HalfFloat(F);
146   #if ERROR
147   HalfFloat(D); // expected-error{{call to 'HalfFloat' is ambiguous}}
148   #endif
151 // Case 5: A function declared with only a double overload.
152 //   (a) When called with half, it will resolve to double because double is a
153 //   valid promotion.
154 //   (b) When called with float it will resolve to double because double is a
155 //   valid promotion.
156 //   (c) When called with double it will resolve to double because it is an
157 //   exact match.
159 // CHECK-LABEL: FunctionDecl {{.*}} Case5 'void (half, float, double)'
160 void Case5(half H, float F, double D) {
161   // CHECK: CallExpr {{.*}} 'void'
162   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
163   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'Double' 'void (double)'
164   Double(H);
166   // CHECK: CallExpr {{.*}} 'void'
167   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
168   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'Double' 'void (double)'
169   Double(F);
171   // CHECK: CallExpr {{.*}} 'void'
172   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(double)' <FunctionToPointerDecay>
173   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (double)' lvalue Function {{.*}} 'Double' 'void (double)'
174   Double(D);
177 // Case 6: A function declared with only a float overload.
178 //   (a) When called with half, it will resolve to float because float is a
179 //   valid promotion.
180 //   (b) When called with float it will resolve to float because float is an
181 //   exact match.
182 //   (c) When called with double it will resolve to float because it is a
183 //   valid conversion.
185 // CHECK-LABEL: FunctionDecl {{.*}} Case6 'void (half, float, double)'
186 void Case6(half H, float F, double D) {
187   // CHECK: CallExpr {{.*}} 'void'
188   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay>
189   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'Float' 'void (float)'
190   Float(H);
192   // CHECK: CallExpr {{.*}} 'void'
193   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay>
194   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'Float' 'void (float)'
195   Float(F);
197   // CHECK: CallExpr {{.*}} 'void'
198   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float)' <FunctionToPointerDecay>
199   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (float)' lvalue Function {{.*}} 'Float' 'void (float)'
200   Float(D); // expected-warning{{implicit conversion loses floating-point precision: 'double' to 'float'}}
203 // Case 7: A function declared with only a half overload.
204 //   (a) When called with half, it will resolve to half because half is an
205 //   exact match
206 //   (b) When called with float it will resolve to half because half is a
207 //   valid conversion.
208 //   (c) When called with double it will resolve to float because it is a
209 //   valid conversion.
211 // CHECK-LABEL: FunctionDecl {{.*}} Case7 'void (half, float, double)'
212 void Case7(half H, float F, double D) {
213   // CHECK: CallExpr {{.*}} 'void'
214   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay>
215   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'Half' 'void (half)'
216   Half(H);
218   // CHECK: CallExpr {{.*}} 'void'
219   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay>
220   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'Half' 'void (half)'
221   Half(F); // expected-warning{{implicit conversion loses floating-point precision: 'float' to 'half'}}
223   // CHECK: CallExpr {{.*}} 'void'
224   // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(half)' <FunctionToPointerDecay>
225   // CHECK-NEXT: DeclRefExpr {{.*}} 'void (half)' lvalue Function {{.*}} 'Half' 'void (half)'
226   Half(D); // expected-warning{{implicit conversion loses floating-point precision: 'double' to 'half'}}