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/resolver/resolver.h"
16
17 #include "gmock/gmock.h"
18 #include "src/resolver/resolver_test_helper.h"
19 #include "src/sem/block_statement.h"
20 #include "src/sem/for_loop_statement.h"
21 #include "src/sem/if_statement.h"
22 #include "src/sem/loop_statement.h"
23 #include "src/sem/switch_statement.h"
24
25 namespace tint {
26 namespace resolver {
27 namespace {
28
29 using ResolverCompoundStatementTest = ResolverTest;
30
TEST_F(ResolverCompoundStatementTest,FunctionBlock)31 TEST_F(ResolverCompoundStatementTest, FunctionBlock) {
32 // fn F() {
33 // var x : 32;
34 // }
35 auto* stmt = Decl(Var("x", ty.i32()));
36 auto* f = Func("F", {}, ty.void_(), {stmt});
37
38 ASSERT_TRUE(r()->Resolve()) << r()->error();
39
40 auto* s = Sem().Get(stmt);
41 ASSERT_NE(s, nullptr);
42 ASSERT_NE(s->Block(), nullptr);
43 ASSERT_TRUE(s->Block()->Is<sem::FunctionBlockStatement>());
44 EXPECT_EQ(s->Block(), s->FindFirstParent<sem::BlockStatement>());
45 EXPECT_EQ(s->Block(), s->FindFirstParent<sem::FunctionBlockStatement>());
46 EXPECT_EQ(s->Function()->Declaration(), f);
47 EXPECT_EQ(s->Block()->Parent(), nullptr);
48 }
49
TEST_F(ResolverCompoundStatementTest,Block)50 TEST_F(ResolverCompoundStatementTest, Block) {
51 // fn F() {
52 // {
53 // var x : 32;
54 // }
55 // }
56 auto* stmt = Decl(Var("x", ty.i32()));
57 auto* block = Block(stmt);
58 auto* f = Func("F", {}, ty.void_(), {block});
59
60 ASSERT_TRUE(r()->Resolve()) << r()->error();
61
62 {
63 auto* s = Sem().Get(block);
64 ASSERT_NE(s, nullptr);
65 EXPECT_TRUE(s->Is<sem::BlockStatement>());
66 EXPECT_EQ(s, s->Block());
67 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
68 }
69 {
70 auto* s = Sem().Get(stmt);
71 ASSERT_NE(s, nullptr);
72 ASSERT_NE(s->Block(), nullptr);
73 EXPECT_EQ(s->Block(), s->FindFirstParent<sem::BlockStatement>());
74 EXPECT_EQ(s->Block()->Parent(),
75 s->FindFirstParent<sem::FunctionBlockStatement>());
76 ASSERT_TRUE(s->Block()->Parent()->Is<sem::FunctionBlockStatement>());
77 EXPECT_EQ(s->Function()->Declaration(), f);
78 EXPECT_EQ(s->Block()->Parent()->Parent(), nullptr);
79 }
80 }
81
TEST_F(ResolverCompoundStatementTest,Loop)82 TEST_F(ResolverCompoundStatementTest, Loop) {
83 // fn F() {
84 // loop {
85 // stmt_a;
86 // continuing {
87 // stmt_b;
88 // }
89 // }
90 // }
91 auto* stmt_a = Ignore(1);
92 auto* stmt_b = Ignore(1);
93 auto* loop = Loop(Block(stmt_a), Block(stmt_b));
94 auto* f = Func("F", {}, ty.void_(), {loop});
95
96 ASSERT_TRUE(r()->Resolve()) << r()->error();
97
98 {
99 auto* s = Sem().Get(loop);
100 ASSERT_NE(s, nullptr);
101 EXPECT_TRUE(s->Is<sem::LoopStatement>());
102 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
103 EXPECT_EQ(s->Parent(), s->Block());
104 }
105 {
106 auto* s = Sem().Get(stmt_a);
107 ASSERT_NE(s, nullptr);
108 ASSERT_NE(s->Block(), nullptr);
109 EXPECT_EQ(s->Parent(), s->Block());
110 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::LoopBlockStatement>());
111
112 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::LoopStatement>());
113 EXPECT_TRUE(Is<sem::LoopStatement>(s->Parent()->Parent()));
114
115 EXPECT_EQ(s->Parent()->Parent()->Parent(),
116 s->FindFirstParent<sem::FunctionBlockStatement>());
117 EXPECT_TRUE(
118 Is<sem::FunctionBlockStatement>(s->Parent()->Parent()->Parent()));
119
120 EXPECT_EQ(s->Function()->Declaration(), f);
121
122 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(), nullptr);
123 }
124 {
125 auto* s = Sem().Get(stmt_b);
126 ASSERT_NE(s, nullptr);
127 ASSERT_NE(s->Block(), nullptr);
128 EXPECT_EQ(s->Parent(), s->Block());
129
130 EXPECT_EQ(s->Parent(),
131 s->FindFirstParent<sem::LoopContinuingBlockStatement>());
132 EXPECT_TRUE(Is<sem::LoopContinuingBlockStatement>(s->Parent()));
133
134 EXPECT_EQ(s->Parent()->Parent(),
135 s->FindFirstParent<sem::LoopBlockStatement>());
136 EXPECT_TRUE(Is<sem::LoopBlockStatement>(s->Parent()->Parent()));
137
138 EXPECT_EQ(s->Parent()->Parent()->Parent(),
139 s->FindFirstParent<sem::LoopStatement>());
140 EXPECT_TRUE(Is<sem::LoopStatement>(s->Parent()->Parent()->Parent()));
141
142 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(),
143 s->FindFirstParent<sem::FunctionBlockStatement>());
144 EXPECT_TRUE(Is<sem::FunctionBlockStatement>(
145 s->Parent()->Parent()->Parent()->Parent()));
146 EXPECT_EQ(s->Function()->Declaration(), f);
147
148 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent()->Parent(), nullptr);
149 }
150 }
151
TEST_F(ResolverCompoundStatementTest,ForLoop)152 TEST_F(ResolverCompoundStatementTest, ForLoop) {
153 // fn F() {
154 // for (var i : u32; true; i = i + 1u) {
155 // return;
156 // }
157 // }
158 auto* init = Decl(Var("i", ty.u32()));
159 auto* cond = Expr(true);
160 auto* cont = Assign("i", Add("i", 1u));
161 auto* stmt = Return();
162 auto* body = Block(stmt);
163 auto* for_ = For(init, cond, cont, body);
164 auto* f = Func("F", {}, ty.void_(), {for_});
165
166 ASSERT_TRUE(r()->Resolve()) << r()->error();
167
168 {
169 auto* s = Sem().Get(for_);
170 ASSERT_NE(s, nullptr);
171 EXPECT_TRUE(s->Is<sem::ForLoopStatement>());
172 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
173 EXPECT_EQ(s->Parent(), s->Block());
174 }
175 {
176 auto* s = Sem().Get(init);
177 ASSERT_NE(s, nullptr);
178 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::ForLoopStatement>());
179 EXPECT_TRUE(Is<sem::ForLoopStatement>(s->Parent()));
180 EXPECT_EQ(s->Block(), s->FindFirstParent<sem::FunctionBlockStatement>());
181 EXPECT_TRUE(Is<sem::FunctionBlockStatement>(s->Parent()->Parent()));
182 }
183 { // Condition expression's statement is the for-loop itself
184 auto* e = Sem().Get(cond);
185 ASSERT_NE(e, nullptr);
186 auto* s = e->Stmt();
187 ASSERT_NE(s, nullptr);
188 ASSERT_TRUE(Is<sem::ForLoopStatement>(s));
189 ASSERT_NE(s->Parent(), nullptr);
190 EXPECT_EQ(s->Parent(), s->Block());
191 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
192 EXPECT_TRUE(Is<sem::FunctionBlockStatement>(s->Block()));
193 }
194 {
195 auto* s = Sem().Get(cont);
196 ASSERT_NE(s, nullptr);
197 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::ForLoopStatement>());
198 EXPECT_TRUE(Is<sem::ForLoopStatement>(s->Parent()));
199 EXPECT_EQ(s->Block(), s->FindFirstParent<sem::FunctionBlockStatement>());
200 EXPECT_TRUE(Is<sem::FunctionBlockStatement>(s->Parent()->Parent()));
201 }
202 {
203 auto* s = Sem().Get(stmt);
204 ASSERT_NE(s, nullptr);
205 ASSERT_NE(s->Block(), nullptr);
206 EXPECT_EQ(s->Parent(), s->Block());
207 EXPECT_EQ(s->Block(), s->FindFirstParent<sem::LoopBlockStatement>());
208 EXPECT_TRUE(Is<sem::ForLoopStatement>(s->Parent()->Parent()));
209 EXPECT_EQ(s->Block()->Parent(),
210 s->FindFirstParent<sem::ForLoopStatement>());
211 ASSERT_TRUE(
212 Is<sem::FunctionBlockStatement>(s->Block()->Parent()->Parent()));
213 EXPECT_EQ(s->Block()->Parent()->Parent(),
214 s->FindFirstParent<sem::FunctionBlockStatement>());
215 EXPECT_EQ(s->Function()->Declaration(), f);
216 EXPECT_EQ(s->Block()->Parent()->Parent()->Parent(), nullptr);
217 }
218 }
219
TEST_F(ResolverCompoundStatementTest,If)220 TEST_F(ResolverCompoundStatementTest, If) {
221 // fn F() {
222 // if (cond_a) {
223 // stat_a;
224 // } elseif (cond_b) {
225 // stat_b;
226 // } else {
227 // stat_c;
228 // }
229 // }
230
231 auto* cond_a = Expr(true);
232 auto* stmt_a = Ignore(1);
233 auto* cond_b = Expr(true);
234 auto* stmt_b = Ignore(1);
235 auto* stmt_c = Ignore(1);
236 auto* if_stmt = If(cond_a, Block(stmt_a), Else(cond_b, Block(stmt_b)),
237 Else(nullptr, Block(stmt_c)));
238 WrapInFunction(if_stmt);
239
240 ASSERT_TRUE(r()->Resolve()) << r()->error();
241
242 {
243 auto* s = Sem().Get(if_stmt);
244 ASSERT_NE(s, nullptr);
245 EXPECT_TRUE(s->Is<sem::IfStatement>());
246 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
247 EXPECT_EQ(s->Parent(), s->Block());
248 }
249 {
250 auto* e = Sem().Get(cond_a);
251 ASSERT_NE(e, nullptr);
252 auto* s = e->Stmt();
253 ASSERT_NE(s, nullptr);
254 EXPECT_TRUE(s->Is<sem::IfStatement>());
255 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
256 EXPECT_EQ(s->Parent(), s->Block());
257 }
258 {
259 auto* s = Sem().Get(stmt_a);
260 ASSERT_NE(s, nullptr);
261 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::BlockStatement>());
262 EXPECT_EQ(s->Parent(), s->Block());
263 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::IfStatement>());
264 EXPECT_EQ(s->Parent()->Parent()->Parent(),
265 s->FindFirstParent<sem::FunctionBlockStatement>());
266 }
267 {
268 auto* e = Sem().Get(cond_b);
269 ASSERT_NE(e, nullptr);
270 auto* s = e->Stmt();
271 ASSERT_NE(s, nullptr);
272 EXPECT_TRUE(s->Is<sem::ElseStatement>());
273 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::IfStatement>());
274 EXPECT_EQ(s->Parent()->Parent(),
275 s->FindFirstParent<sem::FunctionBlockStatement>());
276 EXPECT_EQ(s->Parent()->Parent(), s->Block());
277 }
278 {
279 auto* s = Sem().Get(stmt_b);
280 ASSERT_NE(s, nullptr);
281 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::BlockStatement>());
282 EXPECT_EQ(s->Parent(), s->Block());
283 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::ElseStatement>());
284 EXPECT_EQ(s->Parent()->Parent()->Parent(),
285 s->FindFirstParent<sem::IfStatement>());
286 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(),
287 s->FindFirstParent<sem::FunctionBlockStatement>());
288 }
289 {
290 auto* s = Sem().Get(stmt_c);
291 ASSERT_NE(s, nullptr);
292 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::BlockStatement>());
293 EXPECT_EQ(s->Parent(), s->Block());
294 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::ElseStatement>());
295 EXPECT_EQ(s->Parent()->Parent()->Parent(),
296 s->FindFirstParent<sem::IfStatement>());
297 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(),
298 s->FindFirstParent<sem::FunctionBlockStatement>());
299 }
300 }
301
TEST_F(ResolverCompoundStatementTest,Switch)302 TEST_F(ResolverCompoundStatementTest, Switch) {
303 // fn F() {
304 // switch (expr) {
305 // case 1: {
306 // stmt_a;
307 // }
308 // case 2: {
309 // stmt_b;
310 // }
311 // default: {
312 // stmt_c;
313 // }
314 // }
315 // }
316
317 auto* expr = Expr(5);
318 auto* stmt_a = Ignore(1);
319 auto* stmt_b = Ignore(1);
320 auto* stmt_c = Ignore(1);
321 auto* swi = Switch(expr, Case(Expr(1), Block(stmt_a)),
322 Case(Expr(2), Block(stmt_b)), DefaultCase(Block(stmt_c)));
323 WrapInFunction(swi);
324
325 ASSERT_TRUE(r()->Resolve()) << r()->error();
326
327 {
328 auto* s = Sem().Get(swi);
329 ASSERT_NE(s, nullptr);
330 EXPECT_TRUE(s->Is<sem::SwitchStatement>());
331 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
332 EXPECT_EQ(s->Parent(), s->Block());
333 }
334 {
335 auto* e = Sem().Get(expr);
336 ASSERT_NE(e, nullptr);
337 auto* s = e->Stmt();
338 ASSERT_NE(s, nullptr);
339 EXPECT_TRUE(s->Is<sem::SwitchStatement>());
340 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::FunctionBlockStatement>());
341 EXPECT_EQ(s->Parent(), s->Block());
342 }
343 {
344 auto* s = Sem().Get(stmt_a);
345 ASSERT_NE(s, nullptr);
346 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::BlockStatement>());
347 EXPECT_EQ(s->Parent(), s->Block());
348 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::CaseStatement>());
349 EXPECT_EQ(s->Parent()->Parent()->Parent(),
350 s->FindFirstParent<sem::SwitchStatement>());
351 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(),
352 s->FindFirstParent<sem::FunctionBlockStatement>());
353 }
354 {
355 auto* s = Sem().Get(stmt_b);
356 ASSERT_NE(s, nullptr);
357 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::BlockStatement>());
358 EXPECT_EQ(s->Parent(), s->Block());
359 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::CaseStatement>());
360 EXPECT_EQ(s->Parent()->Parent()->Parent(),
361 s->FindFirstParent<sem::SwitchStatement>());
362 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(),
363 s->FindFirstParent<sem::FunctionBlockStatement>());
364 }
365 {
366 auto* s = Sem().Get(stmt_c);
367 ASSERT_NE(s, nullptr);
368 EXPECT_EQ(s->Parent(), s->FindFirstParent<sem::BlockStatement>());
369 EXPECT_EQ(s->Parent(), s->Block());
370 EXPECT_EQ(s->Parent()->Parent(), s->FindFirstParent<sem::CaseStatement>());
371 EXPECT_EQ(s->Parent()->Parent()->Parent(),
372 s->FindFirstParent<sem::SwitchStatement>());
373 EXPECT_EQ(s->Parent()->Parent()->Parent()->Parent(),
374 s->FindFirstParent<sem::FunctionBlockStatement>());
375 }
376 }
377
378 } // namespace
379 } // namespace resolver
380 } // namespace tint
381