• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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