[RISCV][FMV] Support target_clones (#85786)
[llvm-project.git] / clang / test / SemaHLSL / VectorElementOverloadResolution.hlsl
bloba980cbd252965ee0bad54d2d8260ca48fbc2337f
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
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(double2 D);
15 void HalfFloatDouble(float2 F);
16 void HalfFloatDouble(half2 H);
18 // CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (double2)'
19 // CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (float2)'
20 // CHECK: FunctionDecl {{.*}} used HalfFloatDouble 'void (half2)'
22 void FloatDouble(double2 D); // expected-note {{candidate function}}
23 void FloatDouble(float2 F); // expected-note {{candidate function}}
25 // CHECK: FunctionDecl {{.*}} used FloatDouble 'void (double2)'
26 // CHECK: FunctionDecl {{.*}} used FloatDouble 'void (float2)'
28 void HalfDouble(double2 D);
29 void HalfDouble(half2 H);
31 // CHECK: FunctionDecl {{.*}} used HalfDouble 'void (double2)'
32 // CHECK: FunctionDecl {{.*}} used HalfDouble 'void (half2)'
34 void HalfFloat(float2 F); // expected-note {{candidate function}}
35 void HalfFloat(half2 H); // expected-note {{candidate function}}
37 // CHECK: FunctionDecl {{.*}} used HalfFloat 'void (float2)'
38 // CHECK: FunctionDecl {{.*}} used HalfFloat 'void (half2)'
40 void Double(double2 D);
41 void Float(float2 F);
42 void Half(half2 H);
44 // CHECK: FunctionDecl {{.*}} used Double 'void (double2)'
45 // CHECK: FunctionDecl {{.*}} used Float 'void (float2)'
46 // CHECK: FunctionDecl {{.*}} used Half 'void (half2)'
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.
56 // CHECK-LABEL: FunctionDecl {{.*}} Case1 'void (half2, float2, double2)'
57 void 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);
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);
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);
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.
81 // CHECK-LABEL: FunctionDecl {{.*}} Case2 'void (half2, float2, double2)'
82 void Case2(half2 H, float2 F, double2 D) {
83 #if ERROR
84   FloatDouble(H); // expected-error {{call to 'FloatDouble' is ambiguous}}
85 #endif
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);
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);
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.
106 // CHECK-LABEL: FunctionDecl {{.*}} Case3 'void (half2, float2, double2)'
107 void 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);
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);
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);
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.
131 // CHECK-LABEL: FunctionDecl {{.*}} Case4 'void (half2, float2, double2)'
132 void 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);
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);
143 #if ERROR
144   HalfFloat(D); // expected-error{{call to 'HalfFloat' is ambiguous}}
145 #endif
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.
156 // CHECK-LABEL: FunctionDecl {{.*}} Case5 'void (half2, float2, double2)'
157 void 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);
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);
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);
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.
182 // CHECK-LABEL: FunctionDecl {{.*}} Case6 'void (half2, float2, double2)'
183 void 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);
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);
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)}}
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.
208 // CHECK-LABEL: FunctionDecl {{.*}} Case7 'void (half2, float2, double2)'
209 void 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);
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)}}
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)}}