1 // Copyright 2021 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 "src/ast/break_statement.h"
16 #include "src/ast/continue_statement.h"
17 #include "src/ast/fallthrough_statement.h"
18 #include "src/ast/switch_statement.h"
19 #include "src/resolver/resolver_test_helper.h"
20
21 namespace tint {
22 namespace {
23
24 class ResolverControlBlockValidationTest : public resolver::TestHelper,
25 public testing::Test {};
26
TEST_F(ResolverControlBlockValidationTest,SwitchSelectorExpressionNoneIntegerType_Fail)27 TEST_F(ResolverControlBlockValidationTest,
28 SwitchSelectorExpressionNoneIntegerType_Fail) {
29 // var a : f32 = 3.14;
30 // switch (a) {
31 // default: {}
32 // }
33 auto* var = Var("a", ty.f32(), Expr(3.14f));
34
35 auto* block = Block(Decl(var), Switch(Expr(Source{{12, 34}}, "a"), //
36 DefaultCase()));
37
38 WrapInFunction(block);
39
40 EXPECT_FALSE(r()->Resolve());
41 EXPECT_EQ(r()->error(),
42 "12:34 error: switch statement selector expression must be of a "
43 "scalar integer type");
44 }
45
TEST_F(ResolverControlBlockValidationTest,SwitchWithoutDefault_Fail)46 TEST_F(ResolverControlBlockValidationTest, SwitchWithoutDefault_Fail) {
47 // var a : i32 = 2;
48 // switch (a) {
49 // case 1: {}
50 // }
51 auto* var = Var("a", ty.i32(), Expr(2));
52
53 auto* block = Block(Decl(var), //
54 Switch(Source{{12, 34}}, "a", //
55 Case(Expr(1))));
56
57 WrapInFunction(block);
58
59 EXPECT_FALSE(r()->Resolve());
60 EXPECT_EQ(r()->error(),
61 "12:34 error: switch statement must have a default clause");
62 }
63
TEST_F(ResolverControlBlockValidationTest,SwitchWithTwoDefault_Fail)64 TEST_F(ResolverControlBlockValidationTest, SwitchWithTwoDefault_Fail) {
65 // var a : i32 = 2;
66 // switch (a) {
67 // default: {}
68 // case 1: {}
69 // default: {}
70 // }
71 auto* var = Var("a", ty.i32(), Expr(2));
72
73 auto* block = Block(Decl(var), //
74 Switch("a", //
75 DefaultCase(), //
76 Case(Expr(1)), //
77 DefaultCase(Source{{12, 34}})));
78
79 WrapInFunction(block);
80
81 EXPECT_FALSE(r()->Resolve());
82 EXPECT_EQ(
83 r()->error(),
84 "12:34 error: switch statement must have exactly one default clause");
85 }
86
TEST_F(ResolverControlBlockValidationTest,UnreachableCode_Loop_continue)87 TEST_F(ResolverControlBlockValidationTest, UnreachableCode_Loop_continue) {
88 // loop {
89 // var z: i32;
90 // continue;
91 // z = 1;
92 // }
93 auto* decl_z = Decl(Var("z", ty.i32()));
94 auto* cont = Continue();
95 auto* assign_z = Assign(Source{{12, 34}}, "z", 1);
96 WrapInFunction(Loop(Block(decl_z, cont, assign_z)));
97
98 ASSERT_TRUE(r()->Resolve()) << r()->error();
99 EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable");
100 EXPECT_TRUE(Sem().Get(decl_z)->IsReachable());
101 EXPECT_TRUE(Sem().Get(cont)->IsReachable());
102 EXPECT_FALSE(Sem().Get(assign_z)->IsReachable());
103 }
104
TEST_F(ResolverControlBlockValidationTest,UnreachableCode_Loop_continue_InBlocks)105 TEST_F(ResolverControlBlockValidationTest,
106 UnreachableCode_Loop_continue_InBlocks) {
107 // loop {
108 // var z: i32;
109 // {{{continue;}}}
110 // z = 1;
111 // }
112 auto* decl_z = Decl(Var("z", ty.i32()));
113 auto* cont = Continue();
114 auto* assign_z = Assign(Source{{12, 34}}, "z", 1);
115 WrapInFunction(Loop(Block(decl_z, Block(Block(Block(cont))), assign_z)));
116
117 ASSERT_TRUE(r()->Resolve()) << r()->error();
118 EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable");
119 EXPECT_TRUE(Sem().Get(decl_z)->IsReachable());
120 EXPECT_TRUE(Sem().Get(cont)->IsReachable());
121 EXPECT_FALSE(Sem().Get(assign_z)->IsReachable());
122 }
123
TEST_F(ResolverControlBlockValidationTest,UnreachableCode_ForLoop_continue)124 TEST_F(ResolverControlBlockValidationTest, UnreachableCode_ForLoop_continue) {
125 // for (;;) {
126 // var z: i32;
127 // continue;
128 // z = 1;
129 // }
130 auto* decl_z = Decl(Var("z", ty.i32()));
131 auto* cont = Continue();
132 auto* assign_z = Assign(Source{{12, 34}}, "z", 1);
133 WrapInFunction(For(nullptr, nullptr, nullptr, //
134 Block(decl_z, cont, assign_z)));
135
136 ASSERT_TRUE(r()->Resolve()) << r()->error();
137 EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable");
138 EXPECT_TRUE(Sem().Get(decl_z)->IsReachable());
139 EXPECT_TRUE(Sem().Get(cont)->IsReachable());
140 EXPECT_FALSE(Sem().Get(assign_z)->IsReachable());
141 }
142
TEST_F(ResolverControlBlockValidationTest,UnreachableCode_ForLoop_continue_InBlocks)143 TEST_F(ResolverControlBlockValidationTest,
144 UnreachableCode_ForLoop_continue_InBlocks) {
145 // for (;;) {
146 // var z: i32;
147 // {{{continue;}}}
148 // z = 1;
149 // }
150 auto* decl_z = Decl(Var("z", ty.i32()));
151 auto* cont = Continue();
152 auto* assign_z = Assign(Source{{12, 34}}, "z", 1);
153 WrapInFunction(For(nullptr, nullptr, nullptr,
154 Block(decl_z, Block(Block(Block(cont))), assign_z)));
155
156 ASSERT_TRUE(r()->Resolve()) << r()->error();
157 EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable");
158 EXPECT_TRUE(Sem().Get(decl_z)->IsReachable());
159 EXPECT_TRUE(Sem().Get(cont)->IsReachable());
160 EXPECT_FALSE(Sem().Get(assign_z)->IsReachable());
161 }
162
TEST_F(ResolverControlBlockValidationTest,UnreachableCode_break)163 TEST_F(ResolverControlBlockValidationTest, UnreachableCode_break) {
164 // switch (1) {
165 // case 1: {
166 // var z: i32;
167 // break;
168 // z = 1;
169 // default: {}
170 // }
171 auto* decl_z = Decl(Var("z", ty.i32()));
172 auto* brk = Break();
173 auto* assign_z = Assign(Source{{12, 34}}, "z", 1);
174 WrapInFunction( //
175 Loop(Block(Switch(1, //
176 Case(Expr(1), Block(decl_z, brk, assign_z)), //
177 DefaultCase()))));
178
179 ASSERT_TRUE(r()->Resolve()) << r()->error();
180 EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable");
181 EXPECT_TRUE(Sem().Get(decl_z)->IsReachable());
182 EXPECT_TRUE(Sem().Get(brk)->IsReachable());
183 EXPECT_FALSE(Sem().Get(assign_z)->IsReachable());
184 }
185
TEST_F(ResolverControlBlockValidationTest,UnreachableCode_break_InBlocks)186 TEST_F(ResolverControlBlockValidationTest, UnreachableCode_break_InBlocks) {
187 // loop {
188 // switch (1) {
189 // case 1: { {{{break;}}} var a : u32 = 2;}
190 // default: {}
191 // }
192 // }
193 auto* decl_z = Decl(Var("z", ty.i32()));
194 auto* brk = Break();
195 auto* assign_z = Assign(Source{{12, 34}}, "z", 1);
196 WrapInFunction(Loop(Block(
197 Switch(1, //
198 Case(Expr(1), Block(decl_z, Block(Block(Block(brk))), assign_z)),
199 DefaultCase()))));
200
201 ASSERT_TRUE(r()->Resolve()) << r()->error();
202 EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable");
203 EXPECT_TRUE(Sem().Get(decl_z)->IsReachable());
204 EXPECT_TRUE(Sem().Get(brk)->IsReachable());
205 EXPECT_FALSE(Sem().Get(assign_z)->IsReachable());
206 }
207
TEST_F(ResolverControlBlockValidationTest,SwitchConditionTypeMustMatchSelectorType2_Fail)208 TEST_F(ResolverControlBlockValidationTest,
209 SwitchConditionTypeMustMatchSelectorType2_Fail) {
210 // var a : u32 = 2;
211 // switch (a) {
212 // case 1: {}
213 // default: {}
214 // }
215 auto* var = Var("a", ty.i32(), Expr(2));
216
217 auto* block = Block(Decl(var), Switch("a", //
218 Case(Source{{12, 34}}, {Expr(1u)}), //
219 DefaultCase()));
220 WrapInFunction(block);
221
222 EXPECT_FALSE(r()->Resolve());
223 EXPECT_EQ(r()->error(),
224 "12:34 error: the case selector values must have the same type as "
225 "the selector expression.");
226 }
227
TEST_F(ResolverControlBlockValidationTest,SwitchConditionTypeMustMatchSelectorType_Fail)228 TEST_F(ResolverControlBlockValidationTest,
229 SwitchConditionTypeMustMatchSelectorType_Fail) {
230 // var a : u32 = 2;
231 // switch (a) {
232 // case -1: {}
233 // default: {}
234 // }
235 auto* var = Var("a", ty.u32(), Expr(2u));
236
237 auto* block = Block(Decl(var), //
238 Switch("a", //
239 Case(Source{{12, 34}}, {Expr(-1)}), //
240 DefaultCase()));
241 WrapInFunction(block);
242
243 EXPECT_FALSE(r()->Resolve());
244 EXPECT_EQ(r()->error(),
245 "12:34 error: the case selector values must have the same type as "
246 "the selector expression.");
247 }
248
TEST_F(ResolverControlBlockValidationTest,NonUniqueCaseSelectorValueUint_Fail)249 TEST_F(ResolverControlBlockValidationTest,
250 NonUniqueCaseSelectorValueUint_Fail) {
251 // var a : u32 = 3;
252 // switch (a) {
253 // case 0u: {}
254 // case 2u, 3u, 2u: {}
255 // default: {}
256 // }
257 auto* var = Var("a", ty.u32(), Expr(3u));
258
259 auto* block = Block(Decl(var), //
260 Switch("a", //
261 Case(Expr(0u)),
262 Case({
263 Expr(Source{{12, 34}}, 2u),
264 Expr(3u),
265 Expr(Source{{56, 78}}, 2u),
266 }),
267 DefaultCase()));
268 WrapInFunction(block);
269
270 EXPECT_FALSE(r()->Resolve());
271 EXPECT_EQ(r()->error(),
272 "56:78 error: duplicate switch case '2'\n"
273 "12:34 note: previous case declared here");
274 }
275
TEST_F(ResolverControlBlockValidationTest,NonUniqueCaseSelectorValueSint_Fail)276 TEST_F(ResolverControlBlockValidationTest,
277 NonUniqueCaseSelectorValueSint_Fail) {
278 // var a : i32 = 2;
279 // switch (a) {
280 // case -10: {}
281 // case 0,1,2,-10: {}
282 // default: {}
283 // }
284 auto* var = Var("a", ty.i32(), Expr(2));
285
286 auto* block = Block(Decl(var), //
287 Switch("a", //
288 Case(Expr(Source{{12, 34}}, -10)),
289 Case({
290 Expr(0),
291 Expr(1),
292 Expr(2),
293 Expr(Source{{56, 78}}, -10),
294 }),
295 DefaultCase()));
296 WrapInFunction(block);
297
298 EXPECT_FALSE(r()->Resolve());
299 EXPECT_EQ(r()->error(),
300 "56:78 error: duplicate switch case '-10'\n"
301 "12:34 note: previous case declared here");
302 }
303
TEST_F(ResolverControlBlockValidationTest,LastClauseLastStatementIsFallthrough_Fail)304 TEST_F(ResolverControlBlockValidationTest,
305 LastClauseLastStatementIsFallthrough_Fail) {
306 // var a : i32 = 2;
307 // switch (a) {
308 // default: { fallthrough; }
309 // }
310 auto* var = Var("a", ty.i32(), Expr(2));
311 auto* fallthrough = create<ast::FallthroughStatement>(Source{{12, 34}});
312 auto* block = Block(Decl(var), //
313 Switch("a", //
314 DefaultCase(Block(fallthrough))));
315 WrapInFunction(block);
316
317 EXPECT_FALSE(r()->Resolve());
318 EXPECT_EQ(r()->error(),
319 "12:34 error: a fallthrough statement must not be used in the last "
320 "switch case");
321 }
322
TEST_F(ResolverControlBlockValidationTest,SwitchCase_Pass)323 TEST_F(ResolverControlBlockValidationTest, SwitchCase_Pass) {
324 // var a : i32 = 2;
325 // switch (a) {
326 // default: {}
327 // case 5: {}
328 // }
329 auto* var = Var("a", ty.i32(), Expr(2));
330
331 auto* block = Block(Decl(var), //
332 Switch("a", //
333 DefaultCase(Source{{12, 34}}), //
334 Case(Expr(5))));
335 WrapInFunction(block);
336
337 EXPECT_TRUE(r()->Resolve()) << r()->error();
338 }
339
TEST_F(ResolverControlBlockValidationTest,SwitchCaseAlias_Pass)340 TEST_F(ResolverControlBlockValidationTest, SwitchCaseAlias_Pass) {
341 // type MyInt = u32;
342 // var v: MyInt;
343 // switch(v){
344 // default: {}
345 // }
346
347 auto* my_int = Alias("MyInt", ty.u32());
348 auto* var = Var("a", ty.Of(my_int), Expr(2u));
349 auto* block = Block(Decl(var), //
350 Switch("a", DefaultCase(Source{{12, 34}})));
351
352 WrapInFunction(block);
353
354 EXPECT_TRUE(r()->Resolve()) << r()->error();
355 }
356
357 } // namespace
358 } // namespace tint
359