xref: /llvm-project/clang/test/SemaHLSL/Language/TemplateOutArg.hlsl (revision 89fb8490a99e612f7a574e8678b21a90f689f5b4)
1*89fb8490SChris B// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -finclude-default-header %s -ast-dump | FileCheck %s
2*89fb8490SChris B
3*89fb8490SChris B// Case 1: Template declaration with a call to an inout or out argument that is
4*89fb8490SChris B// resolved based on the template parameter. For this case the template decl
5*89fb8490SChris B// should have an UnresolvedLookupExpr for the call, and the HLSLOutArgExpr is
6*89fb8490SChris B// built during call resolution.
7*89fb8490SChris B
8*89fb8490SChris B// CHECK: FunctionDecl {{.*}} used fn 'void (inout int)'
9*89fb8490SChris Bvoid fn(inout int I) {
10*89fb8490SChris B  I += 1;
11*89fb8490SChris B}
12*89fb8490SChris B
13*89fb8490SChris B// CHECK: FunctionDecl {{.*}} used fn 'void (out double)'
14*89fb8490SChris Bvoid fn(out double F) {
15*89fb8490SChris B  F = 1.5;
16*89fb8490SChris B}
17*89fb8490SChris B
18*89fb8490SChris B// CHECK-LABEL: FunctionTemplateDecl {{.*}} wrapper
19*89fb8490SChris B// CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
20*89fb8490SChris B
21*89fb8490SChris B// Verify that the template has an unresolved call.
22*89fb8490SChris B// CHECK-NEXT: FunctionDecl {{.*}} wrapper 'T (T)'
23*89fb8490SChris B// CHECK-NEXT: ParmVarDecl {{.*}} referenced V 'T'
24*89fb8490SChris B// CHECK: CallExpr {{.*}} '<dependent type>'
25*89fb8490SChris B// CHECK: UnresolvedLookupExpr {{.*}} '<overloaded function type>' lvalue (ADL) = 'fn'
26*89fb8490SChris B
27*89fb8490SChris B// Verify that the int instantiation resolves an inout argument expression.
28*89fb8490SChris B
29*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used wrapper 'int (int)' implicit_instantiation
30*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
31*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' <FunctionToPointerDecay>
32*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)'
33*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout
34*89fb8490SChris B
35*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
36*89fb8490SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'V' 'int'
37*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
38*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
39*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
40*89fb8490SChris B
41*89fb8490SChris B// CHECK: BinaryOperator {{.*}} 'int' lvalue '='
42*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
43*89fb8490SChris B// CHECK: ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
44*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue
45*89fb8490SChris B
46*89fb8490SChris B
47*89fb8490SChris B// Verify that the float instantiation has an out argument expression
48*89fb8490SChris B// containing casts to and from double.
49*89fb8490SChris B
50*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used wrapper 'float (float)' implicit_instantiation
51*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
52*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(out double)' <FunctionToPointerDecay>
53*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}}'void (out double)' lvalue Function {{.*}} 'fn' 'void (out double)'
54*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'double' lvalue out
55*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'float' lvalue
56*89fb8490SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'V' 'float'
57*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'double' lvalue
58*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <FloatingCast>
59*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
60*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'float' lvalue
61*89fb8490SChris B
62*89fb8490SChris B// CHECK: BinaryOperator {{.*}} 'float' lvalue '='
63*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'float' lvalue
64*89fb8490SChris B// CHECK: ImplicitCastExpr {{.*}} 'float' <FloatingCast>
65*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <LValueToRValue>
66*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'double' lvalue
67*89fb8490SChris B
68*89fb8490SChris B
69*89fb8490SChris B// Verify that the double instantiation is just an out expression.
70*89fb8490SChris B
71*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used wrapper 'double (double)' implicit_instantiation
72*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
73*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(out double)' <FunctionToPointerDecay>
74*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}}'void (out double)' lvalue Function {{.*}} 'fn' 'void (out double)'
75*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'double' lvalue out
76*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'double' lvalue
77*89fb8490SChris B// CHECK-NEXT: DeclRefExpr {{.*}} 'double' lvalue ParmVar {{.*}} 'V' 'double'
78*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'double' lvalue
79*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' <LValueToRValue>
80*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'double' lvalue
81*89fb8490SChris B
82*89fb8490SChris B// CHECK: BinaryOperator {{.*}} 'double' lvalue '='
83*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'double' lvalue
84*89fb8490SChris B// CHECK: ImplicitCastExpr {{.*}} 'double' <LValueToRValue>
85*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'double' lvalue
86*89fb8490SChris B
87*89fb8490SChris Btemplate <typename T>
88*89fb8490SChris BT wrapper(T V) {
89*89fb8490SChris B  fn(V);
90*89fb8490SChris B  return V;
91*89fb8490SChris B}
92*89fb8490SChris B
93*89fb8490SChris B// Case 2: Verify that the parameter modifier attribute is instantiated with the
94*89fb8490SChris B// template (this one is a gimme).
95*89fb8490SChris B
96*89fb8490SChris B// CHECK-LABEL: FunctionTemplateDecl {{.*}} fizz
97*89fb8490SChris B
98*89fb8490SChris B// Check the pattern decl.
99*89fb8490SChris B// CHECK: FunctionDecl {{.*}} fizz 'void (inout T)'
100*89fb8490SChris B// CHECK-NEXT: ParmVarDecl {{.*}} referenced V 'T'
101*89fb8490SChris B// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
102*89fb8490SChris B
103*89fb8490SChris B// Check the 3 instantiations (int, float, & double).
104*89fb8490SChris B
105*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used fizz 'void (inout int)' implicit_instantiation
106*89fb8490SChris B// CHECK: ParmVarDecl {{.*}} used V 'int &__restrict'
107*89fb8490SChris B// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
108*89fb8490SChris B
109*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used fizz 'void (inout float)' implicit_instantiation
110*89fb8490SChris B// CHECK: ParmVarDecl {{.*}} used V 'float &__restrict'
111*89fb8490SChris B// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
112*89fb8490SChris B
113*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used fizz 'void (inout double)' implicit_instantiation
114*89fb8490SChris B// CHECK: ParmVarDecl {{.*}} used V 'double &__restrict'
115*89fb8490SChris B// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
116*89fb8490SChris Btemplate <typename T>
117*89fb8490SChris Bvoid fizz(inout T V) {
118*89fb8490SChris B  V += 2;
119*89fb8490SChris B}
120*89fb8490SChris B
121*89fb8490SChris B// Case 3: Verify that HLSLOutArgExpr nodes which are present in the template
122*89fb8490SChris B// are correctly instantiated into the instantation.
123*89fb8490SChris B
124*89fb8490SChris B// First we check that the AST node is in the template.
125*89fb8490SChris B
126*89fb8490SChris B// CHECK-LABEL: FunctionTemplateDecl {{.*}} buzz
127*89fb8490SChris B
128*89fb8490SChris B// CHECK: FunctionDecl {{.*}} buzz 'T (int, T)'
129*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
130*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' <FunctionToPointerDecay>
131*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)'
132*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout
133*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
134*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr  {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int'
135*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
136*89fb8490SChris B// CHECK-NEXT:   ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
137*89fb8490SChris B// CHECK-NEXT:     OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
138*89fb8490SChris B// CHECK:      BinaryOperator {{.*}} 'int' lvalue '='
139*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
140*89fb8490SChris B// CHECK:      ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
141*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue
142*89fb8490SChris B
143*89fb8490SChris B
144*89fb8490SChris B
145*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used buzz 'int (int, int)' implicit_instantiation
146*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
147*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' <FunctionToPointerDecay>
148*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)'
149*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout
150*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
151*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr  {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int'
152*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
153*89fb8490SChris B// CHECK-NEXT:   ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
154*89fb8490SChris B// CHECK-NEXT:     OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
155*89fb8490SChris B// CHECK:      BinaryOperator {{.*}} 'int' lvalue '='
156*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
157*89fb8490SChris B// CHECK:      ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
158*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue
159*89fb8490SChris B
160*89fb8490SChris B
161*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used buzz 'float (int, float)' implicit_instantiation
162*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
163*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' <FunctionToPointerDecay>
164*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)'
165*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout
166*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
167*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr  {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int'
168*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
169*89fb8490SChris B// CHECK-NEXT:   ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
170*89fb8490SChris B// CHECK-NEXT:     OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
171*89fb8490SChris B// CHECK:      BinaryOperator {{.*}} 'int' lvalue '='
172*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
173*89fb8490SChris B// CHECK:      ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
174*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue
175*89fb8490SChris B
176*89fb8490SChris B
177*89fb8490SChris B// CHECK-LABEL: FunctionDecl {{.*}} used buzz 'double (int, double)' implicit_instantiation
178*89fb8490SChris B// CHECK: CallExpr {{.*}} 'void'
179*89fb8490SChris B// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' <FunctionToPointerDecay>
180*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)'
181*89fb8490SChris B// CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout
182*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
183*89fb8490SChris B// CHECK-NEXT:   DeclRefExpr  {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int'
184*89fb8490SChris B// CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue
185*89fb8490SChris B// CHECK-NEXT:   ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
186*89fb8490SChris B// CHECK-NEXT:     OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
187*89fb8490SChris B// CHECK:      BinaryOperator {{.*}} 'int' lvalue '='
188*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue
189*89fb8490SChris B// CHECK:      ImplicitCastExpr  {{.*}} 'int' <LValueToRValue>
190*89fb8490SChris B// CHECK-NEXT:   OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue
191*89fb8490SChris B
192*89fb8490SChris Btemplate <typename T>
193*89fb8490SChris BT buzz(int X, T Y) {
194*89fb8490SChris B  fn(X);
195*89fb8490SChris B  return X + Y;
196*89fb8490SChris B}
197*89fb8490SChris B
198*89fb8490SChris Bexport void caller() {
199*89fb8490SChris B  int X = 2;
200*89fb8490SChris B  float Y = 3.3;
201*89fb8490SChris B  double Z = 2.2;
202*89fb8490SChris B
203*89fb8490SChris B  X = wrapper(X);
204*89fb8490SChris B  Y = wrapper(Y);
205*89fb8490SChris B  Z = wrapper(Z);
206*89fb8490SChris B
207*89fb8490SChris B  fizz(X);
208*89fb8490SChris B  fizz(Y);
209*89fb8490SChris B  fizz(Z);
210*89fb8490SChris B
211*89fb8490SChris B  X = buzz(X, X);
212*89fb8490SChris B  Y = buzz(X, Y);
213*89fb8490SChris B  Z = buzz(X, Z);
214*89fb8490SChris B}
215