| // 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}} | 
 | } |