Files
clang-p2996/clang/test/SemaHLSL/parameter_modifiers.hlsl
Chris B 89fb8490a9 [HLSL] Implement output parameter (#101083)
HLSL output parameters are denoted with the `inout` and `out` keywords
in the function declaration. When an argument to an output parameter is
constructed a temporary value is constructed for the argument.

For `inout` pamameters the argument is initialized via copy-initialization
from the argument lvalue expression to the parameter type. For `out`
parameters the argument is not initialized before the call.

In both cases on return of the function the temporary value is written
back to the argument lvalue expression through an implicit assignment
binary operator with casting as required.

This change introduces a new HLSLOutArgExpr ast node which represents
the output argument behavior. The OutArgExpr has three defined children:
- An OpaqueValueExpr of the argument lvalue expression.
- An OpaqueValueExpr of the copy-initialized parameter.
- A BinaryOpExpr assigning the first with the value of the second.

Fixes #87526

---------

Co-authored-by: Damyan Pepper <damyanp@microsoft.com>
Co-authored-by: John McCall <rjmccall@gmail.com>
2024-08-31 10:59:08 -05:00

101 lines
2.9 KiB
HLSL

// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library %s -verify -Wconversion
void fn(in out float f); // #fn
// expected-error@#fn2{{duplicate parameter modifier 'in'}}
// expected-note@#fn2{{conflicting attribute is here}}
void fn2(in in float f); // #fn2
// expected-error@#fn3{{duplicate parameter modifier 'out'}}
// expected-note@#fn3{{conflicting attribute is here}}
void fn3(out out float f); // #fn3
// expected-error@#fn4{{duplicate parameter modifier 'in'}}
// expected-error@#fn4{{duplicate parameter modifier 'out'}}
// expected-note@#fn4{{conflicting attribute is here}}
// expected-note@#fn4{{conflicting attribute is here}}
void fn4(inout in out float f); // #fn4
// expected-error@#fn5{{duplicate parameter modifier 'in'}}
// expected-note@#fn5{{conflicting attribute is here}}
void fn5(inout in float f); // #fn5
// expected-error@#fn6{{duplicate parameter modifier 'out'}}
// expected-note@#fn6{{conflicting attribute is here}}
void fn6(inout out float f); // #fn6
// expected-error@#fn-def{{conflicting parameter qualifier 'out' on parameter 'f'}}
// expected-note@#fn{{previously declared as 'inout' here}}
void fn(out float f) { // #fn-def
f = 2;
}
// Overload resolution failure.
void fn(in float f); // #fn-in
void failOverloadResolution() {
float f = 1.0;
fn(f); // expected-error{{call to 'fn' is ambiguous}}
// expected-note@#fn{{candidate function}}
// expected-note@#fn-in{{candidate function}}
}
void implicitFn(float f);
void inFn(in float f);
void inoutFn(inout float f); // #inoutFn
void outFn(out float f); // #outFn
void callFns() {
// Call with literal arguments.
implicitFn(1); // Ok.
inFn(1); // Ok.
inoutFn(1); // expected-error{{cannot bind non-lvalue argument 1 to inout paramemter}}
outFn(1); // expected-error{{cannot bind non-lvalue argument 1 to out paramemter}}
// Call with variables.
float f;
implicitFn(f); // Ok.
inFn(f); // Ok.
inoutFn(f); // Ok.
outFn(f); // Ok.
}
// No errors on these scenarios.
// Alternating `inout` and `in out` spellings between declaration and
// definitions is fine since they have the same semantic meaning.
void fn7(inout float f);
void fn7(in out float f) {}
void fn8(in out float f);
void fn8(inout float f) {}
// These two declare two different functions (although calling them will be
// ambiguous). This is equivalent to declaring a function that takes a
// reference and a function that takes a value of the same type.
void fn9(in float f);
void fn9(out float f);
// The `in` attribute is effectively optional. If no attribute is present it is
// the same as `in`, so these declarations match the functions.
void fn10(in float f);
void fn10(float f) {}
void fn11(float f);
void fn11(in float f) {}
template <typename T>
void fn12(inout T f);
void fn13() {
float f;
fn12<float>(f);
}
void fn14(out float f);
void fn15() {
float f;
int x = 5;
fn14(f += x); // expected-warning{{implicit conversion from 'int' to 'float' may lose precision}}
}