// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -finclude-default-header %s -ast-dump | FileCheck %s // Case 1: Template declaration with a call to an inout or out argument that is // resolved based on the template parameter. For this case the template decl // should have an UnresolvedLookupExpr for the call, and the HLSLOutArgExpr is // built during call resolution. // CHECK: FunctionDecl {{.*}} used fn 'void (inout int)' void fn(inout int I) { I += 1; } // CHECK: FunctionDecl {{.*}} used fn 'void (out double)' void fn(out double F) { F = 1.5; } // CHECK-LABEL: FunctionTemplateDecl {{.*}} wrapper // CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T // Verify that the template has an unresolved call. // CHECK-NEXT: FunctionDecl {{.*}} wrapper 'T (T)' // CHECK-NEXT: ParmVarDecl {{.*}} referenced V 'T' // CHECK: CallExpr {{.*}} '' // CHECK: UnresolvedLookupExpr {{.*}} '' lvalue (ADL) = 'fn' // Verify that the int instantiation resolves an inout argument expression. // CHECK-LABEL: FunctionDecl {{.*}} used wrapper 'int (int)' implicit_instantiation // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' // CHECK-NEXT: DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'V' 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: BinaryOperator {{.*}} 'int' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue // Verify that the float instantiation has an out argument expression // containing casts to and from double. // CHECK-LABEL: FunctionDecl {{.*}} used wrapper 'float (float)' implicit_instantiation // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(out double)' // CHECK-NEXT: DeclRefExpr {{.*}}'void (out double)' lvalue Function {{.*}} 'fn' 'void (out double)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'double' lvalue out // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'float' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue ParmVar {{.*}} 'V' 'float' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'double' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'float' lvalue // CHECK: BinaryOperator {{.*}} 'float' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'float' lvalue // CHECK: ImplicitCastExpr {{.*}} 'float' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'double' lvalue // Verify that the double instantiation is just an out expression. // CHECK-LABEL: FunctionDecl {{.*}} used wrapper 'double (double)' implicit_instantiation // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(out double)' // CHECK-NEXT: DeclRefExpr {{.*}}'void (out double)' lvalue Function {{.*}} 'fn' 'void (out double)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'double' lvalue out // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'double' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'double' lvalue ParmVar {{.*}} 'V' 'double' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'double' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'double' lvalue // CHECK: BinaryOperator {{.*}} 'double' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'double' lvalue // CHECK: ImplicitCastExpr {{.*}} 'double' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'double' lvalue template T wrapper(T V) { fn(V); return V; } // Case 2: Verify that the parameter modifier attribute is instantiated with the // template (this one is a gimme). // CHECK-LABEL: FunctionTemplateDecl {{.*}} fizz // Check the pattern decl. // CHECK: FunctionDecl {{.*}} fizz 'void (inout T)' // CHECK-NEXT: ParmVarDecl {{.*}} referenced V 'T' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout // Check the 3 instantiations (int, float, & double). // CHECK-LABEL: FunctionDecl {{.*}} used fizz 'void (inout int)' implicit_instantiation // CHECK: ParmVarDecl {{.*}} used V 'int &__restrict' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout // CHECK-LABEL: FunctionDecl {{.*}} used fizz 'void (inout float)' implicit_instantiation // CHECK: ParmVarDecl {{.*}} used V 'float &__restrict' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout // CHECK-LABEL: FunctionDecl {{.*}} used fizz 'void (inout double)' implicit_instantiation // CHECK: ParmVarDecl {{.*}} used V 'double &__restrict' // CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout template void fizz(inout T V) { V += 2; } // Case 3: Verify that HLSLOutArgExpr nodes which are present in the template // are correctly instantiated into the instantation. // First we check that the AST node is in the template. // CHECK-LABEL: FunctionTemplateDecl {{.*}} buzz // CHECK: FunctionDecl {{.*}} buzz 'T (int, T)' // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' // CHECK-NEXT: DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: BinaryOperator {{.*}} 'int' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue // CHECK-LABEL: FunctionDecl {{.*}} used buzz 'int (int, int)' implicit_instantiation // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' // CHECK-NEXT: DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: BinaryOperator {{.*}} 'int' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue // CHECK-LABEL: FunctionDecl {{.*}} used buzz 'float (int, float)' implicit_instantiation // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' // CHECK-NEXT: DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: BinaryOperator {{.*}} 'int' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue // CHECK-LABEL: FunctionDecl {{.*}} used buzz 'double (int, double)' implicit_instantiation // CHECK: CallExpr {{.*}} 'void' // CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(inout int)' // CHECK-NEXT: DeclRefExpr {{.*}} 'void (inout int)' lvalue Function {{.*}} 'fn' 'void (inout int)' // CHECK-NEXT: HLSLOutArgExpr {{.*}} 'int' lvalue inout // CHECK-NEXT: OpaqueValueExpr [[LVOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'X' 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV:0x[0-9a-fA-F]+]] {{.*}} 'int' lvalue // CHECK-NEXT: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: BinaryOperator {{.*}} 'int' lvalue '=' // CHECK-NEXT: OpaqueValueExpr [[LVOpV]] {{.*}} 'int' lvalue // CHECK: ImplicitCastExpr {{.*}} 'int' // CHECK-NEXT: OpaqueValueExpr [[TmpOpV]] {{.*}} 'int' lvalue template T buzz(int X, T Y) { fn(X); return X + Y; } export void caller() { int X = 2; float Y = 3.3; double Z = 2.2; X = wrapper(X); Y = wrapper(Y); Z = wrapper(Z); fizz(X); fizz(Y); fizz(Z); X = buzz(X, X); Y = buzz(X, Y); Z = buzz(X, Z); }