Files
clang-p2996/clang/test/SemaHLSL/parameter_modifiers_ast.hlsl
Chris B d462621694 [HLSL] Parameter modifier parsing and AST (#72139)
This change implements parsing for HLSL's parameter modifier keywords
`in`, `out` and `inout`. Because HLSL doesn't support references or
pointers, these keywords are used to allow parameters to be passed in
and out of functions.

This change only implements the parsing and AST support. In the HLSL
ASTs we represent `out` and `inout` parameters as references, and we
implement the semantics of by-value passing during IR generation.

In HLSL parameters marked `out` and `inout` are ambiguous in function
declarations, and `in`, `out` and `inout` may be ambiguous at call
sites.

This means a function may be defined as `fn(in T)` and `fn(inout T)` or
`fn(out T)`, but not `fn(inout T)` and `fn(out T)`. If a funciton `fn`
is declared with `in` and `inout` or `out` arguments, the call will be
ambiguous the same as a C++ call would be ambiguous given declarations
`fn(T)` and `fn(T&)`.

Fixes #59849
2023-11-28 15:03:10 -06:00

66 lines
2.4 KiB
HLSL

// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -ast-dump | FileCheck %s
// CHECK: FunctionDecl {{.*}} fn 'void (float)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float'
// CHECK-NOT: HLSLParamModifierAttr
void fn(float f);
// CHECK: FunctionDecl {{.*}}6 fn2 'void (float)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} in
// CHECK-NOT: HLSLParamModifierAttr
void fn2(in float f);
// CHECK: FunctionDecl {{.*}} fn3 'void (float &)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float &'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} out
// CHECK-NOT: HLSLParamModifierAttr
void fn3(out float f);
// CHECK: FunctionDecl {{.*}} fn4 'void (float &)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float &'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
// CHECK-NOT: HLSLParamModifierAttr
void fn4(inout float f);
// CHECK: FunctionDecl {{.*}} fn5 'void (float &)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float &'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout MergedSpelling
// CHECK-NOT: HLSLParamModifierAttr
void fn5(out in float f);
// CHECK: FunctionDecl {{.*}} fn6 'void (float &)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float &'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout MergedSpelling
// CHECK-NOT: HLSLParamModifierAttr
void fn6(in out float f);
// CHECK-NEXT: FunctionTemplateDecl [[Template:0x[0-9a-fA-F]+]] {{.*}} fn7
// CHECK-NEXT: TemplateTypeParmDecl {{.*}} referenced typename depth 0 index 0 T
// CHECK-NEXT: FunctionDecl {{.*}} fn7 'void (T)'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'T'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
// CHECK-NEXT: FunctionDecl [[Instantiation:0x[0-9a-fA-F]+]] {{.*}} used fn7 'void (float &)' implicit_instantiation
// CHECK-NEXT: TemplateArgument type 'float'
// CHECK-NEXT: BuiltinType {{.*}} 'float'
// CHECK-NEXT: ParmVarDecl {{.*}} f 'float &'
// CHECK-NEXT: HLSLParamModifierAttr {{.*}} inout
template <typename T>
void fn7(inout T f);
// CHECK: FunctionDecl {{.*}} fn8 'void ()'
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: DeclStmt
// CHECK-NEXT: VarDecl {{.*}} used f 'float'
// CHECK-NEXT: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float &)' <FunctionToPointerDecay>
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float &)' lvalue
// CHECK-SAME: Function [[Instantiation]] 'fn7' 'void (float &)'
// CHECK-SAME: (FunctionTemplate [[Template]] 'fn7')
// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue Var {{.*}} 'f' 'float'
void fn8() {
float f;
fn7<float>(f);
}