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