attributes.hlsl 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  1. // RUN: %clang_cc1 -fsyntax-only -ffreestanding -verify %s
  2. // To test with the classic compiler, run
  3. // %sdxroot%\tools\x86\fxc.exe /T ps_5_1 attributes.hlsl
  4. // The following is a directive to override default behavior for "VerifyHelper.py fxc RunAttributes". When this is specified, main shader must be defined manually.
  5. // :FXC_VERIFY_ARGUMENTS: /T ps_5_1 /E main
  6. int loop_before_assignment() {
  7. // fxc warning X3554: unknown attribute loop, or attribute invalid for this statement
  8. [loop] // expected-warning {{attribute 'loop' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  9. int val = 2;
  10. return val;
  11. }
  12. int loop_before_return() {
  13. // fxc warning X3554: unknown attribute loop, or attribute invalid for this statement
  14. [loop] // expected-warning {{attribute 'loop' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-warning {{X3554: unknown attribute loop, or attribute invalid for this statement}}
  15. return 0;
  16. }
  17. int loop_before_if(int a) {
  18. [loop] // expected-warning {{attribute 'loop' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  19. if (a > 0) return -a;
  20. return a;
  21. }
  22. int loop_before_switch(int a) {
  23. [loop] // expected-warning {{attribute 'loop' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  24. switch (a) {
  25. case 0:
  26. return 1;
  27. break;
  28. }
  29. return 0;
  30. }
  31. int fastopt_before_if(int a) {
  32. [fastopt] // expected-warning {{attribute 'fastopt' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  33. if (a > 0) return -a;
  34. return a;
  35. }
  36. int fastopt_before_switch(int a) {
  37. [fastopt] // expected-warning {{attribute 'fastopt' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  38. switch (a) {
  39. case 0:
  40. return 1;
  41. break;
  42. }
  43. return 0;
  44. }
  45. int unroll_before_if(int a) {
  46. [unroll] // expected-warning {{attribute 'unroll' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  47. if (a > 0) return -a;
  48. return a;
  49. }
  50. int unroll_before_switch(int a) {
  51. [unroll] // expected-warning {{attribute 'unroll' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  52. switch (a) {
  53. case 0:
  54. return 1;
  55. break;
  56. }
  57. return 0;
  58. }
  59. int allow_uav_condition_before_if(int a) {
  60. [allow_uav_condition] // expected-warning {{attribute 'allow_uav_condition' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  61. if (a > 0) return -a;
  62. return a;
  63. }
  64. int allow_uav_condition_before_switch(int a) {
  65. [allow_uav_condition] // expected-warning {{attribute 'allow_uav_condition' can only be applied to 'for', 'while' and 'do' loop statements}} fxc-pass {{}}
  66. switch (a) {
  67. case 0:
  68. return 1;
  69. break;
  70. }
  71. return 0;
  72. }
  73. int branch_before_for() {
  74. int result = 0;
  75. [branch] // expected-warning {{attribute 'branch' can only be applied to 'if' and 'switch' statements}} fxc-pass {{}}
  76. for (int i = 0; i < 10; i++) result++;
  77. return result;
  78. }
  79. int branch_before_while() {
  80. int result = 0;
  81. int i = 0;
  82. [branch] // expected-warning {{attribute 'branch' can only be applied to 'if' and 'switch' statements}} fxc-pass {{}}
  83. while(i < 10) {
  84. result++;
  85. i++;
  86. }
  87. return result;
  88. }
  89. int branch_before_do() {
  90. int result = 0;
  91. int i = 0;
  92. [branch] // expected-warning {{attribute 'branch' can only be applied to 'if' and 'switch' statements}} fxc-pass {{}}
  93. do {
  94. result++;
  95. i++;
  96. } while(i < 10);
  97. return result;
  98. }
  99. int flatten_before_for() {
  100. int result = 0;
  101. [flatten] // expected-warning {{attribute 'flatten' can only be applied to 'if' and 'switch' statements}} fxc-pass {{}}
  102. for (int i = 0; i < 10; i++) result++;
  103. return result;
  104. }
  105. int flatten_before_while() {
  106. int result = 0;
  107. int i = 0;
  108. [flatten] // expected-warning {{attribute 'flatten' can only be applied to 'if' and 'switch' statements}} fxc-pass {{}}
  109. while(i < 10) {
  110. result++;
  111. i++;
  112. }
  113. return result;
  114. }
  115. int flatten_before_do() {
  116. int result = 0;
  117. int i = 0;
  118. [flatten] // expected-warning {{attribute 'flatten' can only be applied to 'if' and 'switch' statements}} fxc-pass {{}}
  119. do {
  120. result++;
  121. i++;
  122. } while(i < 10);
  123. return result;
  124. }
  125. int forcecase_before_for() {
  126. int result = 0;
  127. [forcecase] // expected-warning {{attribute 'forcecase' can only be applied to 'switch' statements}} fxc-pass {{}}
  128. for (int i = 0; i < 10; i++) result++;
  129. return result;
  130. }
  131. int forcecase_before_while() {
  132. int result = 0;
  133. int i = 0;
  134. [forcecase] // expected-warning {{attribute 'forcecase' can only be applied to 'switch' statements}} fxc-pass {{}}
  135. while(i < 10) {
  136. result++;
  137. i++;
  138. }
  139. return result;
  140. }
  141. int forcecase_before_do() {
  142. int result = 0;
  143. int i = 0;
  144. [forcecase] // expected-warning {{attribute 'forcecase' can only be applied to 'switch' statements}} fxc-pass {{}}
  145. do {
  146. result++;
  147. i++;
  148. } while(i < 10);
  149. return result;
  150. }
  151. int forcecase_before_if(int a) {
  152. [forcecase] // expected-warning {{attribute 'forcecase' can only be applied to 'switch' statements}} fxc-pass {{}}
  153. if (a > 0) return -a;
  154. return a;
  155. }
  156. int call_before_for() {
  157. int result = 0;
  158. [call] // expected-warning {{attribute 'call' can only be applied to 'switch' statements}} fxc-pass {{}}
  159. for (int i = 0; i < 10; i++) result++;
  160. return result;
  161. }
  162. int call_before_while() {
  163. int result = 0;
  164. int i = 0;
  165. [call] // expected-warning {{attribute 'call' can only be applied to 'switch' statements}} fxc-pass {{}}
  166. while(i < 10) {
  167. result++;
  168. i++;
  169. }
  170. return result;
  171. }
  172. int call_before_do() {
  173. int result = 0;
  174. int i = 0;
  175. [call] // expected-warning {{attribute 'call' can only be applied to 'switch' statements}} fxc-pass {{}}
  176. do {
  177. result++;
  178. i++;
  179. } while(i < 10);
  180. return result;
  181. }
  182. int call_before_if(int a) {
  183. [call] // expected-warning {{attribute 'call' can only be applied to 'switch' statements}} fxc-pass {{}}
  184. if (a > 0) return -a;
  185. return a;
  186. }
  187. int short_unroll() {
  188. int result = 2;
  189. [unroll(2)] for (int i = 0; i < 100; i++) result++;
  190. /*verify-ast
  191. AttributedStmt <col:3, col:51>
  192. |-HLSLUnrollAttr <col:4, col:12> 2
  193. `-ForStmt <col:15, col:51>
  194. |-DeclStmt <col:20, col:29>
  195. | `-VarDecl <col:20, col:28> col:24 used i 'int' cinit
  196. | `-ImplicitCastExpr <col:28> 'int' <IntegralCast>
  197. | `-IntegerLiteral <col:28> 'literal int' 0
  198. |-<<<NULL>>>
  199. |-BinaryOperator <col:31, col:35> 'const bool' '<'
  200. | |-ImplicitCastExpr <col:31> 'int' <LValueToRValue>
  201. | | `-DeclRefExpr <col:31> 'int' lvalue Var 'i' 'int'
  202. | `-ImplicitCastExpr <col:35> 'int' <IntegralCast>
  203. | `-IntegerLiteral <col:35> 'literal int' 100
  204. |-UnaryOperator <col:40, col:41> 'int' postfix '++'
  205. | `-DeclRefExpr <col:40> 'int' lvalue Var 'i' 'int'
  206. `-UnaryOperator <col:45, col:51> 'int' postfix '++'
  207. `-DeclRefExpr <col:45> 'int' lvalue Var 'result' 'int'
  208. */
  209. [unroll("2")] // expected-error {{'unroll' attribute requires an integer constant}} fxc-warning {{X3554: cannot match attribute unroll, parameter 1 is expected to be of type int}} fxc-warning {{X3554: unknown attribute unroll, or attribute invalid for this statement, valid attributes are: loop, fastopt, unroll, allow_uav_condition}}
  210. for (int j = 0; j < 100; j++) result++;
  211. return result;
  212. }
  213. int long_unroll() {
  214. int result = 2;
  215. [unroll(200)]
  216. for (int i = 0; i < 100; i++) result++;
  217. return result;
  218. }
  219. int neg_unroll() {
  220. int result = 2;
  221. // fxc error X3084: cannot match attribute unroll, non-uint parameters found
  222. [unroll(-1)] // expected-warning {{attribute 'unroll' must have a uint literal argument}} fxc-error {{X3084: cannot match attribute unroll, non-uint parameters found}}
  223. /*verify-ast
  224. AttributedStmt <col:3, line:277:39>
  225. |-HLSLUnrollAttr <col:4, col:13> -1
  226. `-ForStmt <line:277:3, col:39>
  227. |-DeclStmt <col:8, col:17>
  228. | `-VarDecl <col:8, col:16> col:12 used i 'int' cinit
  229. | `-ImplicitCastExpr <col:16> 'int' <IntegralCast>
  230. | `-IntegerLiteral <col:16> 'literal int' 0
  231. |-<<<NULL>>>
  232. |-BinaryOperator <col:19, col:23> 'const bool' '<'
  233. | |-ImplicitCastExpr <col:19> 'int' <LValueToRValue>
  234. | | `-DeclRefExpr <col:19> 'int' lvalue Var 'i' 'int'
  235. | `-ImplicitCastExpr <col:23> 'int' <IntegralCast>
  236. | `-IntegerLiteral <col:23> 'literal int' 100
  237. |-UnaryOperator <col:28, col:29> 'int' postfix '++'
  238. | `-DeclRefExpr <col:28> 'int' lvalue Var 'i' 'int'
  239. `-UnaryOperator <col:33, col:39> 'int' postfix '++'
  240. `-DeclRefExpr <col:33> 'int' lvalue Var 'result' 'int'
  241. */
  242. for (int i = 0; i < 100; i++) result++;
  243. return result;
  244. }
  245. int flt_unroll() {
  246. int result = 2;
  247. // fxc warning X3554: cannot match attribute unroll, parameter 1 is expected to be of type int
  248. // fxc warning X3554: unknown attribute unroll, or attribute invalid for this statement, valid attributes are: loop, fastopt, unroll, allow_uav_condition
  249. [unroll(1.5)] // expected-warning {{attribute 'unroll' must have a uint literal argument}} fxc-warning {{X3554: cannot match attribute unroll, parameter 1 is expected to be of type int}} fxc-warning {{X3554: unknown attribute unroll, or attribute invalid for this statement, valid attributes are: loop, fastopt, unroll, allow_uav_condition}}
  250. /*verify-ast
  251. AttributedStmt <col:3, line:307:39>
  252. |-HLSLUnrollAttr <col:4, col:14> 0
  253. `-ForStmt <line:307:3, col:39>
  254. |-DeclStmt <col:8, col:17>
  255. | `-VarDecl <col:8, col:16> col:12 used i 'int' cinit
  256. | `-ImplicitCastExpr <col:16> 'int' <IntegralCast>
  257. | `-IntegerLiteral <col:16> 'literal int' 0
  258. |-<<<NULL>>>
  259. |-BinaryOperator <col:19, col:23> 'const bool' '<'
  260. | |-ImplicitCastExpr <col:19> 'int' <LValueToRValue>
  261. | | `-DeclRefExpr <col:19> 'int' lvalue Var 'i' 'int'
  262. | `-ImplicitCastExpr <col:23> 'int' <IntegralCast>
  263. | `-IntegerLiteral <col:23> 'literal int' 100
  264. |-UnaryOperator <col:28, col:29> 'int' postfix '++'
  265. | `-DeclRefExpr <col:28> 'int' lvalue Var 'i' 'int'
  266. `-UnaryOperator <col:33, col:39> 'int' postfix '++'
  267. `-DeclRefExpr <col:33> 'int' lvalue Var 'result' 'int'
  268. */
  269. for (int i = 0; i < 100; i++) result++;
  270. return result;
  271. }
  272. RWByteAddressBuffer bab;
  273. int bab_address;
  274. bool g_bool;
  275. uint g_uint;
  276. uint g_dealiasTableOffset;
  277. uint g_dealiasTableSize;
  278. int uav() {
  279. // fxc not complaining.
  280. //int result = bab_address;
  281. //while (bab.Load(result) != 0) {
  282. // bab.Store(bab_address, g_dealiasTableOffset - result);
  283. // result++;
  284. //}
  285. //return result;
  286. uint i;
  287. [allow_uav_condition]
  288. /*verify-ast
  289. AttributedStmt <col:3, line:348:3>
  290. |-HLSLAllowUAVConditionAttr <col:4>
  291. `-ForStmt <line:347:3, line:348:3>
  292. |-BinaryOperator <col:8, col:12> 'uint':'unsigned int' '='
  293. | |-DeclRefExpr <col:8> 'uint':'unsigned int' lvalue Var 'i' 'uint':'unsigned int'
  294. | `-ImplicitCastExpr <col:12> 'uint':'unsigned int' <LValueToRValue>
  295. | `-DeclRefExpr <col:12> 'const uint':'const unsigned int' lvalue Var 'g_dealiasTableOffset' 'const uint':'const unsigned int'
  296. |-<<<NULL>>>
  297. |-BinaryOperator <col:34, col:38> 'const bool' '<'
  298. | |-ImplicitCastExpr <col:34> 'uint':'unsigned int' <LValueToRValue>
  299. | | `-DeclRefExpr <col:34> 'uint':'unsigned int' lvalue Var 'i' 'uint':'unsigned int'
  300. | `-ImplicitCastExpr <col:38> 'uint':'unsigned int' <LValueToRValue>
  301. | `-DeclRefExpr <col:38> 'const uint':'const unsigned int' lvalue Var 'g_dealiasTableSize' 'const uint':'const unsigned int'
  302. |-UnaryOperator <col:58, col:60> 'uint':'unsigned int' lvalue prefix '++'
  303. | `-DeclRefExpr <col:60> 'uint':'unsigned int' lvalue Var 'i' 'uint':'unsigned int'
  304. `-CompoundStmt <col:63, line:348:3>
  305. */
  306. for (i = g_dealiasTableOffset; i < g_dealiasTableSize; ++i) {
  307. }
  308. return i;
  309. }
  310. [domain] int domain_fn_missing() { return 1; } // expected-error {{'domain' attribute takes one argument}} fxc-pass {{}}
  311. [domain()] int domain_fn_empty() { return 1; } // expected-error {{'domain' attribute takes one argument}} fxc-error {{X3000: syntax error: unexpected token ')'}}
  312. [domain("blerch")] int domain_fn_bad() { return 1; } // expected-error {{attribute 'domain' must have one of these values: tri,quad,isoline}} fxc-pass {{}}
  313. [domain("quad")] int domain_fn() { return 1; } /* fxc-warning {{X3554: unknown attribute domain, or attribute invalid for this statement}} */
  314. [domain(1)] int domain_fn_int() { return 1; } // expected-error {{attribute 'domain' must have a string literal argument}} fxc-pass {{}}
  315. [domain("quad","quad")] int domain_fn_mul() { return 1; } // expected-error {{'domain' attribute takes one argument}} fxc-pass {{}}
  316. [instance] int instance_fn() { return 1; } // expected-error {{'instance' attribute takes one argument}} fxc-warning {{X3554: unknown attribute instance, or attribute invalid for this statement}}
  317. [maxtessfactor] int maxtessfactor_fn() { return 1; } // expected-error {{'maxtessfactor' attribute takes one argument}} fxc-warning {{X3554: unknown attribute maxtessfactor, or attribute invalid for this statement}}
  318. [numthreads] int numthreads_fn() { return 1; } // expected-error {{'numthreads' attribute requires exactly 3 arguments}} fxc-warning {{X3554: unknown attribute numthreads, or attribute invalid for this statement}}
  319. [outputcontrolpoints] int outputcontrolpoints_fn() { return 1; } // expected-error {{'outputcontrolpoints' attribute takes one argument}} fxc-warning {{X3554: unknown attribute outputcontrolpoints, or attribute invalid for this statement}}
  320. [outputtopology] int outputtopology_fn() { return 1; } // expected-error {{'outputtopology' attribute takes one argument}} fxc-warning {{X3554: unknown attribute outputtopology, or attribute invalid for this statement}}
  321. [partitioning] int partitioning_fn() { return 1; } // expected-error {{'partitioning' attribute takes one argument}} fxc-warning {{X3554: unknown attribute partitioning, or attribute invalid for this statement}}
  322. [patchconstantfunc] int patchconstantfunc_fn() { return 1; } // expected-error {{'patchconstantfunc' attribute takes one argument}} fxc-warning {{X3554: unknown attribute patchconstantfunc, or attribute invalid for this statement}}
  323. [partitioning("fractional_even")] int partitioning_fn_ok() { return 1; }
  324. struct HSFoo
  325. {
  326. float3 pos : POSITION;
  327. };
  328. Texture2D<float4> tex1[10] : register( t20, space10 );
  329. /*verify-ast
  330. VarDecl <col:1, col:26> col:19 used tex1 'Texture2D<float4> [10]'
  331. `-RegisterAssignment <col:30> register(t20, space10)
  332. */
  333. [domain(123)] // expected-error {{attribute 'domain' must have a string literal argument}} fxc-pass {{}}
  334. [partitioning()] // expected-error {{'partitioning' attribute takes one argument}} fxc-error {{X3000: syntax error: unexpected token ')'}}
  335. [outputtopology("not_triangle_cw")] // expected-error {{attribute 'outputtopology' must have one of these values: point,line,triangle,triangle_cw,triangle_ccw}} fxc-pass {{}}
  336. [outputcontrolpoints(-1)] // expected-warning {{attribute 'outputcontrolpoints' must have a uint literal argument}} fxc-pass {{}}
  337. [patchconstantfunc("PatchFoo", "ExtraArgument")] // expected-error {{'patchconstantfunc' attribute takes one argument}} fxc-pass {{}}
  338. void all_wrong() { }
  339. [domain("quad")]
  340. /*verify-ast
  341. HLSLDomainAttr <col:2, col:15> "quad"
  342. */
  343. [partitioning("integer")]
  344. [outputtopology("triangle_cw")]
  345. [outputcontrolpoints(16)]
  346. [patchconstantfunc("PatchFoo")]
  347. HSFoo HSMain( InputPatch<HSFoo, 16> p,
  348. /*verify-ast
  349. FunctionDecl <col:1, line:468:1> line:394:7 HSMain 'HSFoo (InputPatch<HSFoo, 16>, uint, uint)'
  350. |-ParmVarDecl <col:15, col:37> col:37 used p 'InputPatch<HSFoo, 16>':'InputPatch<HSFoo, 16>'
  351. |-ParmVarDecl <line:460:15, col:20> col:20 used i 'uint':'unsigned int'
  352. | `-SemanticDecl <col:24> "SV_OutputControlPointID"
  353. |-ParmVarDecl <line:461:15, col:20> col:20 used PatchID 'uint':'unsigned int'
  354. | `-SemanticDecl <col:30> "SV_PrimitiveID"
  355. |-CompoundStmt <line:462:1, line:468:1>
  356. | |-DeclStmt <line:463:5, col:17>
  357. | | `-VarDecl <col:5, col:11> col:11 used output 'HSFoo' nrvo
  358. | |-DeclStmt <line:464:5, col:41>
  359. | | `-VarDecl <col:5, col:40> col:12 used r 'float4':'vector<float, 4>' cinit
  360. | | `-CXXFunctionalCastExpr <col:16, col:40> 'float4':'vector<float, 4>' functional cast to float4 <NoOp>
  361. | | `-InitListExpr <col:23, col:39> 'float4':'vector<float, 4>'
  362. | | |-ImplicitCastExpr <col:23, col:34> 'const float3':'const vector<float, 3>' <LValueToRValue>
  363. | | | `-MemberExpr <col:23, col:34> 'const float3':'const vector<float, 3>' lvalue .pos
  364. | | | `-CXXOperatorCallExpr <col:23, col:32> 'const HSFoo' lvalue
  365. | | | |-ImplicitCastExpr <col:24, col:32> 'const HSFoo &(*)(unsigned int) const' <FunctionToPointerDecay>
  366. | | | | `-DeclRefExpr <col:24, col:32> 'const HSFoo &(unsigned int) const' lvalue CXXMethod 'operator[]' 'const HSFoo &(unsigned int) const'
  367. | | | |-ImplicitCastExpr <col:23> 'const InputPatch<HSFoo, 16>' lvalue <NoOp>
  368. | | | | `-DeclRefExpr <col:23> 'InputPatch<HSFoo, 16>':'InputPatch<HSFoo, 16>' lvalue ParmVar 'p' 'InputPatch<HSFoo, 16>':'InputPatch<HSFoo, 16>'
  369. | | | `-ImplicitCastExpr <col:25> 'uint':'unsigned int' <LValueToRValue>
  370. | | | `-DeclRefExpr <col:25> 'uint':'unsigned int' lvalue ParmVar 'PatchID' 'uint':'unsigned int'
  371. | | `-ImplicitCastExpr <col:39> 'float' <IntegralToFloating>
  372. | | `-IntegerLiteral <col:39> 'literal int' 1
  373. | |-CompoundAssignOperator <line:465:5, col:30> 'float4':'vector<float, 4>' lvalue '+=' ComputeLHSTy='float4':'vector<float, 4>' ComputeResultTy='float4':'vector<float, 4>'
  374. | | |-DeclRefExpr <col:5> 'float4':'vector<float, 4>' lvalue Var 'r' 'float4':'vector<float, 4>'
  375. | | `-CXXMemberCallExpr <col:10, col:30> 'vector<float, 4>'
  376. | | |-MemberExpr <col:10, col:20> '<bound member function type>' .Load
  377. | | | `-ArraySubscriptExpr <col:10, col:18> 'Texture2D<float4>':'Texture2D<vector<float, 4> >' lvalue
  378. | | | |-ImplicitCastExpr <col:10> 'Texture2D<float4> [10]' <LValueToRValue>
  379. | | | | `-DeclRefExpr <col:10> 'Texture2D<float4> [10]' lvalue Var 'tex1' 'Texture2D<float4> [10]'
  380. | | | `-ImplicitCastExpr <col:15, col:17> 'unsigned int' <FloatingToIntegral>
  381. | | | `-ImplicitCastExpr <col:15, col:17> 'float' <LValueToRValue>
  382. | | | `-HLSLVectorElementExpr <col:15, col:17> 'float' lvalue vectorcomponent x
  383. | | | `-DeclRefExpr <col:15> 'float4':'vector<float, 4>' lvalue Var 'r' 'float4':'vector<float, 4>'
  384. | | `-ImplicitCastExpr <col:25, col:27> 'vector<int, 3>' <HLSLCC_FloatingToIntegral>
  385. | | `-ImplicitCastExpr <col:25, col:27> 'vector<float, 3>':'vector<float, 3>' <LValueToRValue>
  386. | | `-HLSLVectorElementExpr <col:25, col:27> 'vector<float, 3>':'vector<float, 3>' lvalue vectorcomponent xyz
  387. | | `-DeclRefExpr <col:25> 'float4':'vector<float, 4>' lvalue Var 'r' 'float4':'vector<float, 4>'
  388. | |-BinaryOperator <line:466:5, col:31> 'float3':'vector<float, 3>' '='
  389. | | |-MemberExpr <col:5, col:12> 'float3':'vector<float, 3>' lvalue .pos
  390. | | | `-DeclRefExpr <col:5> 'HSFoo' lvalue Var 'output' 'HSFoo'
  391. | | `-BinaryOperator <col:18, col:31> 'float3':'vector<float, 3>' '+'
  392. | | |-ImplicitCastExpr <col:18, col:23> 'float3':'vector<float, 3>' <LValueToRValue>
  393. | | | `-MemberExpr <col:18, col:23> 'const float3':'const vector<float, 3>' lvalue .pos
  394. | | | `-CXXOperatorCallExpr <col:18, col:21> 'const HSFoo' lvalue
  395. | | | |-ImplicitCastExpr <col:19, col:21> 'const HSFoo &(*)(unsigned int) const' <FunctionToPointerDecay>
  396. | | | | `-DeclRefExpr <col:19, col:21> 'const HSFoo &(unsigned int) const' lvalue CXXMethod 'operator[]' 'const HSFoo &(unsigned int) const'
  397. | | | |-ImplicitCastExpr <col:18> 'const InputPatch<HSFoo, 16>' lvalue <NoOp>
  398. | | | | `-DeclRefExpr <col:18> 'InputPatch<HSFoo, 16>':'InputPatch<HSFoo, 16>' lvalue ParmVar 'p' 'InputPatch<HSFoo, 16>':'InputPatch<HSFoo, 16>'
  399. | | | `-ImplicitCastExpr <col:20> 'uint':'unsigned int' <LValueToRValue>
  400. | | | `-DeclRefExpr <col:20> 'uint':'unsigned int' lvalue ParmVar 'i' 'uint':'unsigned int'
  401. | | `-ImplicitCastExpr <col:29, col:31> 'vector<float, 3>':'vector<float, 3>' <LValueToRValue>
  402. | | `-HLSLVectorElementExpr <col:29, col:31> 'vector<float, 3>':'vector<float, 3>' lvalue vectorcomponent xyz
  403. | | `-DeclRefExpr <col:29> 'float4':'vector<float, 4>' lvalue Var 'r' 'float4':'vector<float, 4>'
  404. | `-ReturnStmt <line:467:5, col:12>
  405. | `-ImplicitCastExpr <col:12> 'HSFoo' <LValueToRValue>
  406. | `-DeclRefExpr <col:12> 'HSFoo' lvalue Var 'output' 'HSFoo'
  407. |-HLSLPatchConstantFuncAttr <line:393:2, col:30> "PatchFoo"
  408. |-HLSLOutputControlPointsAttr <line:392:2, col:24> 16
  409. |-HLSLOutputTopologyAttr <line:391:2, col:30> "triangle_cw"
  410. |-HLSLPartitioningAttr <line:390:2, col:24> "integer"
  411. `-HLSLDomainAttr <line:386:2, col:15> "quad"
  412. */
  413. uint i : SV_OutputControlPointID,
  414. uint PatchID : SV_PrimitiveID )
  415. {
  416. HSFoo output;
  417. float4 r = float4(p[PatchID].pos, 1);
  418. r += tex1[r.x].Load(r.xyz);
  419. output.pos = p[i].pos + r.xyz;
  420. return output;
  421. }
  422. float4 cp4[2];
  423. int4 i4;
  424. float4 cp5;
  425. float4x4 m4;
  426. float f;
  427. struct global_struct { float4 cp5[5]; };
  428. struct main_output
  429. {
  430. //float4 t0 : SV_Target0;
  431. float4 p0 : SV_Position0;
  432. };
  433. float4 myexpr() { return cp5; }
  434. static const float4 f4_const = float4(1, 2, 3, 4);
  435. bool b;
  436. int clip_index;
  437. static const bool b_true = true;
  438. global_struct gs;
  439. float4 f4;
  440. //
  441. // Things we can't do in clipplanes:
  442. //
  443. // - use literal in any part of expression
  444. // - use static const in any part of expression
  445. // - use ternary operator
  446. // - use binary operator
  447. // - make function calls
  448. // - use indexed expressions
  449. // - implicit conversions
  450. // - explicit conversions
  451. //
  452. // fxc error X3084: Clip plane attribute parameters must be non-literal constants
  453. [clipplanes(float4(1, 2, f, 4))] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  454. void clipplanes_literals();
  455. [clipplanes(b)] // expected-error {{clipplanes argument must be a float4 type but is 'const bool'}} fxc-pass {{}}
  456. void clipplanes_const();
  457. // fxc error X3084: Clip plane attribute parameters must be non-literal constants
  458. [clipplanes(f4_const)] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  459. void clipplanes_const();
  460. // fxc error X3084: Clip plane attribute parameters must be non-literal constants
  461. [clipplanes(b ? cp4[clip_index] : cp4[clip_index])] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  462. void clipplanes_bad_ternary();
  463. // fxc error X3084: Clip plane attribute parameters must be non-literal constants
  464. [clipplanes(cp5 + cp5)] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  465. void clipplanes_bad_binop();
  466. // fxc error X3682: expressions with side effects are illegal as attribute parameters
  467. [clipplanes(myexpr())] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  468. void clipplanes_bad_call();
  469. // fxc error X3084: Indexed expressions are illegal as attribute parameters
  470. [clipplanes(cp4[clip_index])] // expected-error {{invalid expression for clipplanes argument array subscript: must be numeric literal}} fxc-pass {{}}
  471. void clipplanes_bad_indexed();
  472. //
  473. // Thing we can do in clipplanes:
  474. //
  475. // - index into array
  476. // - index into vector
  477. // - swizzle (even into an rvalue, even from scalar)
  478. // - member access
  479. // - constructors
  480. //
  481. // index into swizzle into r-value - allowed in fxc, disallowed in new compiler
  482. [clipplanes(cp4[0].xyzw)] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  483. void clipplanes_bad_swizzle();
  484. // index into vector - allowed in fxc, disallowed in new compiler
  485. [clipplanes(cp4[0][0].xxxx)] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  486. void clipplanes_bad_vector_index();
  487. // index into matrix - allowed in fxc, disallowed in new compiler
  488. [clipplanes(m4[0])] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  489. void clipplanes_bad_matrix_index();
  490. // constructor - allowed in fxc, disallowed in new compiler
  491. [clipplanes(float4(f, f, f, f))] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  492. void clipplanes_bad_matrix_index();
  493. // swizzle from scalar - allowed in fxc, disallowed in new compiler
  494. [clipplanes(f.xxxx)] // expected-error {{invalid expression for clipplanes argument: must be global reference, member access or array subscript}} fxc-pass {{}}
  495. void clipplanes_bad_scalar_swizzle();
  496. [clipplanes(
  497. /*verify-ast
  498. HLSLClipPlanesAttr <col:2, line:582:3>
  499. |-DeclRefExpr <line:579:3> 'const float4':'const vector<float, 4>' lvalue Var 'f4' 'const float4':'const vector<float, 4>'
  500. |-ArraySubscriptExpr <line:580:3, col:8> 'const float4':'const vector<float, 4>' lvalue
  501. | |-ImplicitCastExpr <col:3> 'const float4 [2]' <LValueToRValue>
  502. | | `-DeclRefExpr <col:3> 'const float4 [2]' lvalue Var 'cp4' 'const float4 [2]'
  503. | `-IntegerLiteral <col:7> 'literal int' 0
  504. |-ArraySubscriptExpr <line:581:3, col:11> 'float4':'vector<float, 4>' lvalue
  505. | |-ImplicitCastExpr <col:3, col:6> 'float4 [5]' <LValueToRValue>
  506. | | `-MemberExpr <col:3, col:6> 'float4 const[5]' lvalue .cp5
  507. | | `-DeclRefExpr <col:3> 'const global_struct' lvalue Var 'gs' 'const global_struct'
  508. | `-IntegerLiteral <col:10> 'literal int' 2
  509. |-<<<NULL>>>
  510. |-<<<NULL>>>
  511. `-<<<NULL>>>
  512. */
  513. f4, // simple global reference
  514. cp4[0], // index into array
  515. gs.cp5[2] // use '.' operator
  516. )]
  517. float4 clipplanes_good();
  518. [clipplanes(
  519. /*verify-ast
  520. HLSLClipPlanesAttr <col:2, line:616:3>
  521. |-ParenExpr <line:612:3, col:6> 'const float4':'const vector<float, 4>' lvalue
  522. | `-DeclRefExpr <col:4> 'const float4':'const vector<float, 4>' lvalue Var 'f4' 'const float4':'const vector<float, 4>'
  523. |-ArraySubscriptExpr <line:613:3, col:10> 'const float4':'const vector<float, 4>' lvalue
  524. | |-ImplicitCastExpr <col:3> 'const float4 [2]' <LValueToRValue>
  525. | | `-DeclRefExpr <col:3> 'const float4 [2]' lvalue Var 'cp4' 'const float4 [2]'
  526. | `-ParenExpr <col:7, col:9> 'literal int'
  527. | `-IntegerLiteral <col:8> 'literal int' 0
  528. |-ArraySubscriptExpr <line:614:3, col:13> 'float4':'vector<float, 4>' lvalue
  529. | |-ImplicitCastExpr <col:3, col:8> 'float4 [5]' <LValueToRValue>
  530. | | `-MemberExpr <col:3, col:8> 'float4 const[5]' lvalue .cp5
  531. | | `-ParenExpr <col:3, col:6> 'const global_struct' lvalue
  532. | | `-DeclRefExpr <col:4> 'const global_struct' lvalue Var 'gs' 'const global_struct'
  533. | `-IntegerLiteral <col:12> 'literal int' 2
  534. |-ParenExpr <line:615:3, col:15> 'float4':'vector<float, 4>' lvalue
  535. | `-ArraySubscriptExpr <col:4, col:14> 'float4':'vector<float, 4>' lvalue
  536. | |-ImplicitCastExpr <col:4, col:9> 'float4 [5]' <LValueToRValue>
  537. | | `-MemberExpr <col:4, col:9> 'float4 const[5]' lvalue .cp5
  538. | | `-ParenExpr <col:4, col:7> 'const global_struct' lvalue
  539. | | `-DeclRefExpr <col:5> 'const global_struct' lvalue Var 'gs' 'const global_struct'
  540. | `-IntegerLiteral <col:13> 'literal int' 2
  541. |-<<<NULL>>>
  542. `-<<<NULL>>>
  543. */
  544. (f4), // simple global reference
  545. cp4[(0)], // index into array
  546. (gs).cp5[2], // use '.' operator
  547. ((gs).cp5[2]) // use '.' operator
  548. )]
  549. float4 clipplanes_good_parens();
  550. // GS Attribute maxvertexcount
  551. // Note: fxc only reports errors when function is the entry, therefore, I will
  552. // place the errors in comments before the function, but not with the standard
  553. // fxc error comments on the line.
  554. struct GSVertex { float4 pos : SV_Position; };
  555. [maxvertexcount (12)]
  556. /*verify-ast
  557. HLSLMaxVertexCountAttr <col:2, col:20> 12
  558. */
  559. void maxvertexcount_valid1(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  560. { stream.Append(v[0]); }
  561. static const int sc_count = 12;
  562. [maxvertexcount (sc_count)]
  563. /*verify-ast
  564. HLSLMaxVertexCountAttr <col:2, col:26> 12
  565. */
  566. void maxvertexcount_valid2(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  567. { stream.Append(v[0]); }
  568. [maxvertexcount (sc_count + 3)]
  569. /*verify-ast
  570. HLSLMaxVertexCountAttr <col:2, col:30> 15
  571. */
  572. void maxvertexcount_valid3(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  573. { stream.Append(v[0]); }
  574. static const int4 sc_count4 = int4(3,6,9,12);
  575. // The following passes fxc, but fails clang.
  576. [maxvertexcount (sc_count4.w)] /* expected-error {{'maxvertexcount' attribute requires an integer constant}} fxc-pass {{}} */
  577. /*verify-ast
  578. HLSLMaxVertexCountAttr <col:2, col:29> 0
  579. */
  580. void maxvertexcount_valid4(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  581. { stream.Append(v[0]); }
  582. // fxc:
  583. // error X3084: cannot match attribute maxvertexcount, non-uint parameters found
  584. [maxvertexcount (-12)] /* expected-warning {{attribute 'maxvertexcount' must have a uint literal argument}} fxc-pass {{}} */
  585. void negative_maxvertexcount(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  586. { stream.Append(v[0]); }
  587. // fxc:
  588. // warning X3554: cannot match attribute maxvertexcount, parameter 1 is expected to be of type int
  589. // warning X3554: unknown attribute maxvertexcount, or attribute invalid for this statement, valid attributes are: maxvertexcount, MaxVertexCount, instance, RootSignature
  590. // error X3514: 'float_maxvertexcount1' must have a max vertex count
  591. [maxvertexcount (1.5)] /* expected-warning {{attribute 'maxvertexcount' must have a uint literal argument}} fxc-pass {{}} */
  592. void float_maxvertexcount1(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  593. { stream.Append(v[0]); }
  594. // fxc:
  595. // warning X3554: cannot match attribute maxvertexcount, parameter 1 is expected to be of type int
  596. // warning X3554: unknown attribute maxvertexcount, or attribute invalid for this statement, valid attributes are: maxvertexcount, MaxVertexCount, instance, RootSignature
  597. // error X3514: 'float_maxvertexcount2' must have a max vertex count
  598. static const float sc_float = 1.5;
  599. [maxvertexcount (sc_float)] /* expected-error {{'maxvertexcount' attribute requires an integer constant}} fxc-pass {{}} */
  600. void float_maxvertexcount2(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  601. { stream.Append(v[0]); }
  602. int i_count;
  603. float f_count;
  604. // fxc:
  605. // error X3084: non-literal parameter(s) found for attribute maxvertexcount
  606. // error X3514: 'uniform_maxvertexcount1' must have a max vertex count
  607. [maxvertexcount (i_count)] /* expected-error {{'maxvertexcount' attribute requires an integer constant}} fxc-pass {{}} */
  608. void uniform_maxvertexcount1(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  609. { stream.Append(v[0]); }
  610. // fxc:
  611. // warning X3554: cannot match attribute maxvertexcount, parameter 1 is expected to be of type int
  612. // warning X3554: unknown attribute maxvertexcount, or attribute invalid for this statement, valid attributes are: maxvertexcount, MaxVertexCount, instance, RootSignature
  613. // error X3514: 'uniform_maxvertexcount2' must have a max vertex count
  614. [maxvertexcount (f_count)] /* expected-error {{'maxvertexcount' attribute requires an integer constant}} fxc-pass {{}} */
  615. void uniform_maxvertexcount2(triangle GSVertex v[3], inout TriangleStream<GSVertex> stream)
  616. { stream.Append(v[0]); }
  617. [earlydepthstencil]
  618. /*verify-ast
  619. HLSLEarlyDepthStencilAttr <col:2>
  620. */
  621. float4 main() : SV_Target0 {
  622. int val = 2;
  623. [earlydepthstencil] // expected-error {{attribute is valid only on functions}} fxc-pass {{}}
  624. float2 f2 = { 1, 2 };
  625. [loop]
  626. for (int i = 0; i < 4; i++) { // expected-note {{previous definition is here}} fxc-pass {{}}
  627. val *= 2;
  628. }
  629. [unroll]
  630. // fxc warning X3078: 'i': loop control variable conflicts with a previous declaration in the outer scope; most recent declaration will be used
  631. for (int i = 0; i < 4; i++) { // expected-warning {{redefinition of 'i' shadows declaration in the outer scope; most recent declaration will be used}} fxc-warning {{X3078: 'i': loop control variable conflicts with a previous declaration in the outer scope; most recent declaration will be used}}
  632. val *= 2;
  633. }
  634. // fxc error X3524: can't use loop and unroll attributes together
  635. [loop][unroll] // expected-error {{loop and unroll attributes are not compatible}} fxc-error {{X3524: can't use loop and unroll attributes together}}
  636. for (int k = 0; k < 4; k++) { val *= 2; } // expected-note {{previous definition is here}} fxc-pass {{}}
  637. // fxc error X3524: can't use fastopt and unroll attributes together
  638. [fastopt][unroll] // expected-error {{fastopt and unroll attributes are not compatible}} fxc-error {{X3524: can't use fastopt and unroll attributes together}}
  639. for (int k = 0; k < 4; k++) { val *= 2; } // expected-warning {{redefinition of 'k' shadows declaration in the outer scope; most recent declaration will be used}} fxc-pass {{}}
  640. loop_before_assignment();
  641. loop_before_return();
  642. val = 2;
  643. [loop]
  644. do { val *= 2; } while (val < 10);
  645. [fastopt]
  646. while (val > 10) { val--; }
  647. [branch]
  648. if (g_bool) {
  649. val += 4;
  650. }
  651. [flatten]
  652. if (!g_bool) {
  653. val += 4;
  654. }
  655. [flatten]
  656. switch (g_uint) {
  657. // fxc error X3533: non-empty case statements must have break or return
  658. // case 0: val += 100;
  659. case 1: val += 101; break;
  660. case 2:
  661. case 3: val += 102; break;
  662. break;
  663. }
  664. [branch]
  665. switch (g_uint) {
  666. case 1: val += 101; break;
  667. case 2:
  668. case 3: val += 102; break;
  669. break;
  670. }
  671. [forcecase]
  672. switch (g_uint) {
  673. case 1: val += 101; break;
  674. case 2:
  675. case 3: val += 102; break;
  676. break;
  677. }
  678. [call]
  679. switch (g_uint) {
  680. case 1: val += 101; break;
  681. case 2:
  682. case 3: val += 102; break;
  683. break;
  684. }
  685. val += domain_fn();
  686. val += instance_fn();
  687. val += maxtessfactor_fn();
  688. val += numthreads_fn();
  689. val += outputcontrolpoints_fn();
  690. val += outputtopology_fn();
  691. val += partitioning_fn();
  692. val += patchconstantfunc_fn();
  693. val += long_unroll();
  694. val += short_unroll();
  695. val += neg_unroll();
  696. val += flt_unroll();
  697. val += uav();
  698. return val;
  699. }
  700. // Test support for title case in attributes.
  701. // Test Allow_UAV_Condition
  702. bool Test_Allow_UAV_Condition() {
  703. [Allow_UAV_Condition]
  704. while (1) { return true; }
  705. }
  706. // Test Branch
  707. bool Test_Branch() {
  708. [Branch]
  709. if (g_bool) return true; else return false;
  710. }
  711. // Test Call
  712. bool Test_Call() {
  713. [Call]
  714. switch (g_uint) {
  715. case 1: return true;
  716. default: return false;
  717. }
  718. }
  719. // Test EarlyDepthStencil
  720. [EarlyDepthStencil]
  721. bool Test_EarlyDepthStencil() {
  722. return true;
  723. }
  724. // Test FastOpt
  725. bool Test_FastOpt() {
  726. [FastOpt] while (g_bool) return g_bool;
  727. }
  728. // Test Flatten
  729. bool Test_Flatten() {
  730. [Flatten] if (g_bool) return true; else return false;
  731. }
  732. // Test Forcecase
  733. bool Test_Forcecase() {
  734. [ForceCase]
  735. switch (g_uint) {
  736. case 1: return true;
  737. default: return false;
  738. }
  739. }
  740. // Test Loop
  741. bool Test_Loop() {
  742. [Loop] while (g_bool) return g_bool;
  743. }
  744. // Test ClipPlanes
  745. float4 ClipPlanesVal;
  746. [ClipPlanes(ClipPlanesVal)]
  747. bool Test_ClipPlanes() {
  748. return true;
  749. }
  750. // Test Domain
  751. [Domain("tri")]
  752. bool Test_Domain() {
  753. return true;
  754. }
  755. // Test Instance
  756. [Instance(1)]
  757. bool Test_Instance() {
  758. return true;
  759. }
  760. // Test MaxTessFactor
  761. [MaxTessFactor(1)]
  762. bool Test_MaxTessFactor() {
  763. return true;
  764. }
  765. // Test MaxVertexCount
  766. [MaxVertexCount(1)]
  767. bool Test_MaxVertexCount() {
  768. return true;
  769. }
  770. // Test NumThreads
  771. [NumThreads(1,2,3)]
  772. bool Test_NumThreads() {
  773. return true;
  774. }
  775. // Test OutputControlPoints
  776. [OutputControlPoints(2)]
  777. bool Test_OutputControlPoints() {
  778. return true;
  779. }
  780. // Test OutputTopology
  781. [OutputTopology("line")]
  782. bool Test_OutputTopology() {
  783. return true;
  784. }
  785. // Test Partitioning
  786. [Partitioning("integer")]
  787. bool Test_Partitioning() {
  788. return true;
  789. }
  790. // Test PatchConstantFunc
  791. [PatchConstantFunc("Test_Partitioning")]
  792. bool Test_PatchConstantFunc() {
  793. return true;
  794. }
  795. // Test RootSignature
  796. [RootSignature("")]
  797. bool Test_RootSignature() {
  798. return true;
  799. }
  800. // Test Unroll
  801. bool Test_Unroll() {
  802. [Unroll] while (g_bool) return g_bool;
  803. }
  804. // Test NoInline
  805. [noinline] bool Test_noinline() {
  806. [noinline] bool b = false; /* expected-warning {{'noinline' attribute only applies to functions}} fxc-pass {{}} */
  807. [noinline] while (g_bool) return g_bool; /* expected-error {{'noinline' attribute cannot be applied to a statement}} fxc-pass {{}} */
  808. return true;
  809. }
  810. // Test unknown attribute warning
  811. bool Test_Unknown() {
  812. [unknown] bool b1 = false; /* expected-warning {{unknown attribute 'unknown' ignored}} fxc-pass {{}} */
  813. [unknown(1)] bool b2 = false; /* expected-warning {{unknown attribute 'unknown' ignored}} fxc-pass {{}} */
  814. [unknown(1)] while (g_bool) return g_bool; /* expected-warning {{unknown attribute 'unknown' ignored}} fxc-pass {{}} */
  815. }