1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "gtest/gtest.h"
16 #include "spirv/unified1/GLSL.std.450.h"
17 #include "src/ast/case_statement.h"
18 #include "src/ast/fallthrough_statement.h"
19 #include "src/ast/return_statement.h"
20 #include "src/ast/scalar_constructor_expression.h"
21 #include "src/ast/sint_literal.h"
22 #include "src/ast/switch_statement.h"
23 #include "src/ast/type/alias_type.h"
24 #include "src/ast/type/f32_type.h"
25 #include "src/ast/type/i32_type.h"
26 #include "src/ast/type/u32_type.h"
27 #include "src/ast/uint_literal.h"
28 #include "src/ast/variable.h"
29 #include "src/ast/variable_decl_statement.h"
30 #include "src/type_determiner.h"
31 #include "src/validator/validator_impl.h"
32 #include "src/validator/validator_test_helper.h"
33 
34 namespace tint {
35 namespace {
36 
37 class ValidateControlBlockTest : public ValidatorTestHelper,
38                                  public testing::Test {};
39 
TEST_F(ValidateControlBlockTest,SwitchSelectorExpressionNoneIntegerType_Fail)40 TEST_F(ValidateControlBlockTest, SwitchSelectorExpressionNoneIntegerType_Fail) {
41   // var a : f32 = 3.14;
42   // switch (a) {
43   //   default: {}
44   // }
45   ast::type::F32Type f32;
46   auto var =
47       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &f32);
48   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
49       std::make_unique<ast::SintLiteral>(&f32, 3.14f)));
50 
51   auto cond = std::make_unique<ast::IdentifierExpression>(
52       Source{Source::Location{12, 34}}, "a");
53   ast::CaseSelectorList default_csl;
54   auto block_default = std::make_unique<ast::BlockStatement>();
55   ast::CaseStatementList body;
56   body.push_back(std::make_unique<ast::CaseStatement>(
57       std::move(default_csl), std::move(block_default)));
58 
59   auto block = std::make_unique<ast::BlockStatement>();
60   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
61   block->append(
62       std::make_unique<ast::SwitchStatement>(std::move(cond), std::move(body)));
63 
64   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
65   EXPECT_FALSE(v()->ValidateStatements(block.get()));
66   EXPECT_EQ(v()->error(),
67             "12:34: v-0025: switch statement selector expression must be "
68             "of a scalar integer type");
69 }
70 
TEST_F(ValidateControlBlockTest,SwitchWithoutDefault_Fail)71 TEST_F(ValidateControlBlockTest, SwitchWithoutDefault_Fail) {
72   // var a : i32 = 2;
73   // switch (a) {
74   //   case 1: {}
75   // }
76   ast::type::I32Type i32;
77   auto var =
78       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &i32);
79   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
80       std::make_unique<ast::SintLiteral>(&i32, 2)));
81 
82   auto cond = std::make_unique<ast::IdentifierExpression>("a");
83   ast::CaseSelectorList csl;
84   csl.push_back(std::make_unique<ast::SintLiteral>(&i32, 1));
85   ast::CaseStatementList body;
86   body.push_back(std::make_unique<ast::CaseStatement>(
87       std::move(csl), std::make_unique<ast::BlockStatement>()));
88 
89   auto block = std::make_unique<ast::BlockStatement>();
90   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
91   block->append(std::make_unique<ast::SwitchStatement>(
92       Source{Source::Location{12, 34}}, std::move(cond), std::move(body)));
93 
94   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
95   EXPECT_FALSE(v()->ValidateStatements(block.get()));
96   EXPECT_EQ(v()->error(),
97             "12:34: v-0008: switch statement must have exactly one default "
98             "clause");
99 }
100 
TEST_F(ValidateControlBlockTest,SwitchWithTwoDefault_Fail)101 TEST_F(ValidateControlBlockTest, SwitchWithTwoDefault_Fail) {
102   // var a : i32 = 2;
103   // switch (a) {
104   //   default: {}
105   //   case 1: {}
106   //   default: {}
107   // }
108   ast::type::I32Type i32;
109   auto var =
110       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &i32);
111   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
112       std::make_unique<ast::SintLiteral>(&i32, 2)));
113 
114   ast::CaseStatementList switch_body;
115   auto cond = std::make_unique<ast::IdentifierExpression>("a");
116 
117   ast::CaseSelectorList default_csl_1;
118   auto block_default_1 = std::make_unique<ast::BlockStatement>();
119   switch_body.push_back(std::make_unique<ast::CaseStatement>(
120       std::move(default_csl_1), std::move(block_default_1)));
121 
122   ast::CaseSelectorList csl_case_1;
123   csl_case_1.push_back(std::make_unique<ast::SintLiteral>(&i32, 1));
124   auto block_case_1 = std::make_unique<ast::BlockStatement>();
125   switch_body.push_back(std::make_unique<ast::CaseStatement>(
126       std::move(csl_case_1), std::move(block_case_1)));
127 
128   ast::CaseSelectorList default_csl_2;
129   auto block_default_2 = std::make_unique<ast::BlockStatement>();
130   switch_body.push_back(std::make_unique<ast::CaseStatement>(
131       std::move(default_csl_2), std::move(block_default_2)));
132 
133   auto block = std::make_unique<ast::BlockStatement>();
134   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
135   block->append(std::make_unique<ast::SwitchStatement>(
136       Source{Source::Location{12, 34}}, std::move(cond),
137       std::move(switch_body)));
138 
139   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
140   EXPECT_FALSE(v()->ValidateStatements(block.get()));
141   EXPECT_EQ(v()->error(),
142             "12:34: v-0008: switch statement must have exactly one default "
143             "clause");
144 }
145 
TEST_F(ValidateControlBlockTest,SwitchConditionTypeMustMatchSelectorType2_Fail)146 TEST_F(ValidateControlBlockTest,
147        SwitchConditionTypeMustMatchSelectorType2_Fail) {
148   // var a : i32 = 2;
149   // switch (a) {
150   //   case 1: {}
151   //   default: {}
152   // }
153   ast::type::U32Type u32;
154   ast::type::I32Type i32;
155   auto var =
156       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &i32);
157   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
158       std::make_unique<ast::SintLiteral>(&i32, 2)));
159 
160   ast::CaseStatementList switch_body;
161   auto cond = std::make_unique<ast::IdentifierExpression>("a");
162 
163   ast::CaseSelectorList csl;
164   csl.push_back(std::make_unique<ast::UintLiteral>(&u32, 1));
165   switch_body.push_back(std::make_unique<ast::CaseStatement>(
166       Source{Source::Location{12, 34}}, std::move(csl),
167       std::make_unique<ast::BlockStatement>()));
168 
169   ast::CaseSelectorList default_csl;
170   auto block_default = std::make_unique<ast::BlockStatement>();
171   switch_body.push_back(std::make_unique<ast::CaseStatement>(
172       std::move(default_csl), std::move(block_default)));
173 
174   auto block = std::make_unique<ast::BlockStatement>();
175   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
176   block->append(std::make_unique<ast::SwitchStatement>(std::move(cond),
177                                                        std::move(switch_body)));
178 
179   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
180   EXPECT_FALSE(v()->ValidateStatements(block.get()));
181   EXPECT_EQ(v()->error(),
182             "12:34: v-0026: the case selector values must have the same "
183             "type as the selector expression.");
184 }
185 
TEST_F(ValidateControlBlockTest,SwitchConditionTypeMustMatchSelectorType_Fail)186 TEST_F(ValidateControlBlockTest,
187        SwitchConditionTypeMustMatchSelectorType_Fail) {
188   // var a : u32 = 2;
189   // switch (a) {
190   //   case -1: {}
191   //   default: {}
192   // }
193   ast::type::U32Type u32;
194   ast::type::I32Type i32;
195   auto var =
196       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &u32);
197   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
198       std::make_unique<ast::UintLiteral>(&u32, 2)));
199 
200   ast::CaseStatementList switch_body;
201   auto cond = std::make_unique<ast::IdentifierExpression>("a");
202 
203   ast::CaseSelectorList csl;
204   csl.push_back(std::make_unique<ast::SintLiteral>(&i32, -1));
205   switch_body.push_back(std::make_unique<ast::CaseStatement>(
206       Source{Source::Location{12, 34}}, std::move(csl),
207       std::make_unique<ast::BlockStatement>()));
208 
209   ast::CaseSelectorList default_csl;
210   auto block_default = std::make_unique<ast::BlockStatement>();
211   switch_body.push_back(std::make_unique<ast::CaseStatement>(
212       std::move(default_csl), std::move(block_default)));
213 
214   auto block = std::make_unique<ast::BlockStatement>();
215   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
216   block->append(std::make_unique<ast::SwitchStatement>(std::move(cond),
217                                                        std::move(switch_body)));
218 
219   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
220   EXPECT_FALSE(v()->ValidateStatements(block.get()));
221   EXPECT_EQ(v()->error(),
222             "12:34: v-0026: the case selector values must have the same "
223             "type as the selector expression.");
224 }
225 
TEST_F(ValidateControlBlockTest,NonUniqueCaseSelectorValueUint_Fail)226 TEST_F(ValidateControlBlockTest, NonUniqueCaseSelectorValueUint_Fail) {
227   // var a : u32 = 3;
228   // switch (a) {
229   //   case 0: {}
230   //   case 2, 2: {}
231   //   default: {}
232   // }
233   ast::type::U32Type u32;
234   auto var =
235       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &u32);
236   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
237       std::make_unique<ast::UintLiteral>(&u32, 3)));
238 
239   ast::CaseStatementList switch_body;
240   auto cond = std::make_unique<ast::IdentifierExpression>("a");
241 
242   ast::CaseSelectorList csl_1;
243   csl_1.push_back(std::make_unique<ast::UintLiteral>(&u32, 0));
244   switch_body.push_back(std::make_unique<ast::CaseStatement>(
245       std::move(csl_1), std::make_unique<ast::BlockStatement>()));
246 
247   ast::CaseSelectorList csl_2;
248   csl_2.push_back(std::make_unique<ast::UintLiteral>(&u32, 2));
249   csl_2.push_back(std::make_unique<ast::UintLiteral>(&u32, 2));
250   switch_body.push_back(std::make_unique<ast::CaseStatement>(
251       Source{Source::Location{12, 34}}, std::move(csl_2),
252       std::make_unique<ast::BlockStatement>()));
253 
254   ast::CaseSelectorList default_csl;
255   auto block_default = std::make_unique<ast::BlockStatement>();
256   switch_body.push_back(std::make_unique<ast::CaseStatement>(
257       std::move(default_csl), std::move(block_default)));
258 
259   auto block = std::make_unique<ast::BlockStatement>();
260   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
261   block->append(std::make_unique<ast::SwitchStatement>(std::move(cond),
262                                                        std::move(switch_body)));
263 
264   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
265   EXPECT_FALSE(v()->ValidateStatements(block.get()));
266   EXPECT_EQ(v()->error(),
267             "12:34: v-0027: a literal value must not appear more than once "
268             "in the case selectors for a switch statement: '2'");
269 }
270 
TEST_F(ValidateControlBlockTest,NonUniqueCaseSelectorValueSint_Fail)271 TEST_F(ValidateControlBlockTest, NonUniqueCaseSelectorValueSint_Fail) {
272   // var a : i32 = 2;
273   // switch (a) {
274   //   case 10: {}
275   //   case 0,1,2,10: {}
276   //   default: {}
277   // }
278   ast::type::I32Type i32;
279   auto var =
280       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &i32);
281   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
282       std::make_unique<ast::SintLiteral>(&i32, 2)));
283 
284   ast::CaseStatementList switch_body;
285   auto cond = std::make_unique<ast::IdentifierExpression>("a");
286 
287   ast::CaseSelectorList csl_1;
288   csl_1.push_back(std::make_unique<ast::SintLiteral>(&i32, 10));
289   switch_body.push_back(std::make_unique<ast::CaseStatement>(
290       std::move(csl_1), std::make_unique<ast::BlockStatement>()));
291 
292   ast::CaseSelectorList csl_2;
293   csl_2.push_back(std::make_unique<ast::SintLiteral>(&i32, 0));
294   csl_2.push_back(std::make_unique<ast::SintLiteral>(&i32, 1));
295   csl_2.push_back(std::make_unique<ast::SintLiteral>(&i32, 2));
296   csl_2.push_back(std::make_unique<ast::SintLiteral>(&i32, 10));
297   switch_body.push_back(std::make_unique<ast::CaseStatement>(
298       Source{Source::Location{12, 34}}, std::move(csl_2),
299       std::make_unique<ast::BlockStatement>()));
300 
301   ast::CaseSelectorList default_csl;
302   auto block_default = std::make_unique<ast::BlockStatement>();
303   switch_body.push_back(std::make_unique<ast::CaseStatement>(
304       std::move(default_csl), std::move(block_default)));
305 
306   auto block = std::make_unique<ast::BlockStatement>();
307   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
308   block->append(std::make_unique<ast::SwitchStatement>(std::move(cond),
309                                                        std::move(switch_body)));
310 
311   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
312   EXPECT_FALSE(v()->ValidateStatements(block.get()));
313   EXPECT_EQ(v()->error(),
314             "12:34: v-0027: a literal value must not appear more than once in "
315             "the case selectors for a switch statement: '10'");
316 }
317 
TEST_F(ValidateControlBlockTest,LastClauseLastStatementIsFallthrough_Fail)318 TEST_F(ValidateControlBlockTest, LastClauseLastStatementIsFallthrough_Fail) {
319   // var a : i32 = 2;
320   // switch (a) {
321   //   default: { fallthrough; }
322   // }
323   ast::type::I32Type i32;
324   auto var =
325       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &i32);
326   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
327       std::make_unique<ast::SintLiteral>(&i32, 2)));
328 
329   auto cond = std::make_unique<ast::IdentifierExpression>("a");
330   ast::CaseSelectorList default_csl;
331   auto block_default = std::make_unique<ast::BlockStatement>();
332   block_default->append(std::make_unique<ast::FallthroughStatement>(
333       Source{Source::Location{12, 34}}));
334   ast::CaseStatementList body;
335   body.push_back(std::make_unique<ast::CaseStatement>(
336       std::move(default_csl), std::move(block_default)));
337 
338   auto block = std::make_unique<ast::BlockStatement>();
339   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
340   block->append(
341       std::make_unique<ast::SwitchStatement>(std::move(cond), std::move(body)));
342 
343   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
344   EXPECT_FALSE(v()->ValidateStatements(block.get()));
345   EXPECT_EQ(v()->error(),
346             "12:34: v-0028: a fallthrough statement must not appear as the "
347             "last statement in last clause of a switch");
348 }
349 
TEST_F(ValidateControlBlockTest,SwitchCase_Pass)350 TEST_F(ValidateControlBlockTest, SwitchCase_Pass) {
351   // var a : i32 = 2;
352   // switch (a) {
353   //   default: {}
354   //   case 5: {}
355   // }
356   ast::type::I32Type i32;
357   auto var =
358       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &i32);
359   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
360       std::make_unique<ast::SintLiteral>(&i32, 2)));
361 
362   auto cond = std::make_unique<ast::IdentifierExpression>("a");
363   ast::CaseSelectorList default_csl;
364   auto block_default = std::make_unique<ast::BlockStatement>();
365   ast::CaseStatementList body;
366   body.push_back(std::make_unique<ast::CaseStatement>(
367       Source{Source::Location{12, 34}}, std::move(default_csl),
368       std::move(block_default)));
369   ast::CaseSelectorList case_csl;
370   case_csl.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
371   auto block_case = std::make_unique<ast::BlockStatement>();
372   body.push_back(std::make_unique<ast::CaseStatement>(std::move(case_csl),
373                                                       std::move(block_case)));
374 
375   auto block = std::make_unique<ast::BlockStatement>();
376   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
377   block->append(
378       std::make_unique<ast::SwitchStatement>(std::move(cond), std::move(body)));
379 
380   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
381   EXPECT_TRUE(v()->ValidateStatements(block.get())) << v()->error();
382 }
383 
TEST_F(ValidateControlBlockTest,SwitchCaseAlias_Pass)384 TEST_F(ValidateControlBlockTest, SwitchCaseAlias_Pass) {
385   // type MyInt = u32;
386   // var v: MyInt;
387   // switch(v){
388   //   default: {}
389   // }
390 
391   ast::type::U32Type u32;
392   ast::type::AliasType my_int{"MyInt", &u32};
393 
394   auto var =
395       std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &my_int);
396   var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
397       std::make_unique<ast::SintLiteral>(&u32, 2)));
398 
399   auto cond = std::make_unique<ast::IdentifierExpression>("a");
400   ast::CaseSelectorList default_csl;
401   auto block_default = std::make_unique<ast::BlockStatement>();
402   ast::CaseStatementList body;
403   body.push_back(std::make_unique<ast::CaseStatement>(
404       Source{Source::Location{12, 34}}, std::move(default_csl),
405       std::move(block_default)));
406 
407   auto block = std::make_unique<ast::BlockStatement>();
408   block->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
409   block->append(
410       std::make_unique<ast::SwitchStatement>(std::move(cond), std::move(body)));
411 
412   mod()->AddConstructedType(&my_int);
413 
414   EXPECT_TRUE(td()->DetermineStatements(block.get())) << td()->error();
415   EXPECT_TRUE(v()->ValidateStatements(block.get())) << v()->error();
416 }
417 
418 }  // namespace
419 }  // namespace tint
420