blob: 927006582117672c878115f7f0dc53be8cea2f0c [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// 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/tint/resolver/resolver.h"
16
17#include "gmock/gmock.h"
18#include "gtest/gtest-spi.h"
19#include "src/tint/ast/assignment_statement.h"
20#include "src/tint/ast/bitcast_expression.h"
21#include "src/tint/ast/break_statement.h"
22#include "src/tint/ast/builtin_texture_helper_test.h"
23#include "src/tint/ast/call_statement.h"
24#include "src/tint/ast/continue_statement.h"
25#include "src/tint/ast/discard_statement.h"
26#include "src/tint/ast/if_statement.h"
27#include "src/tint/ast/loop_statement.h"
28#include "src/tint/ast/return_statement.h"
29#include "src/tint/ast/stage_attribute.h"
30#include "src/tint/ast/switch_statement.h"
31#include "src/tint/ast/unary_op_expression.h"
32#include "src/tint/ast/variable_decl_statement.h"
33#include "src/tint/resolver/resolver_test_helper.h"
34#include "src/tint/sem/call.h"
35#include "src/tint/sem/function.h"
36#include "src/tint/sem/member_accessor_expression.h"
Tint teamf4626062022-05-06 08:50:33 +000037#include "src/tint/sem/sampled_texture.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000038#include "src/tint/sem/statement.h"
39#include "src/tint/sem/variable.h"
40
41using ::testing::ElementsAre;
42using ::testing::HasSubstr;
43
Tint teamf4626062022-05-06 08:50:33 +000044using namespace tint::number_suffixes; // NOLINT
45
Tint teamd2323c52022-04-11 20:49:10 +000046namespace tint::resolver {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000047namespace {
48
49using ResolverValidationTest = ResolverTest;
50
Ben Clayton41f8d2a2022-03-07 18:37:46 +000051class FakeStmt final : public Castable<FakeStmt, ast::Statement> {
Tint teamf4626062022-05-06 08:50:33 +000052 public:
53 FakeStmt(ProgramID pid, Source src) : Base(pid, src) {}
54 FakeStmt* Clone(CloneContext*) const override { return nullptr; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000055};
56
Ben Clayton41f8d2a2022-03-07 18:37:46 +000057class FakeExpr final : public Castable<FakeExpr, ast::Expression> {
Tint teamf4626062022-05-06 08:50:33 +000058 public:
59 FakeExpr(ProgramID pid, Source src) : Base(pid, src) {}
60 FakeExpr* Clone(CloneContext*) const override { return nullptr; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000061};
62
63TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInVertexStage) {
Tint teamf4626062022-05-06 08:50:33 +000064 Global(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::StorageClass::kWorkgroup);
65 Global("dst", ty.vec4<f32>(), ast::StorageClass::kPrivate);
66 auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
Ryan Harrisondbc13af2022-02-21 15:19:07 +000067
Tint teamf4626062022-05-06 08:50:33 +000068 Func(Source{{9, 10}}, "f0", ast::VariableList{}, ty.vec4<f32>(), {stmt, Return(Expr("dst"))},
69 ast::AttributeList{Stage(ast::PipelineStage::kVertex)},
70 ast::AttributeList{Builtin(ast::Builtin::kPosition)});
Ryan Harrisondbc13af2022-02-21 15:19:07 +000071
Tint teamf4626062022-05-06 08:50:33 +000072 EXPECT_FALSE(r()->Resolve());
73 EXPECT_EQ(r()->error(),
74 "3:4 error: workgroup memory cannot be used by vertex pipeline "
75 "stage\n1:2 note: variable is declared here");
Ryan Harrisondbc13af2022-02-21 15:19:07 +000076}
77
78TEST_F(ResolverValidationTest, WorkgroupMemoryUsedInFragmentStage) {
Tint teamf4626062022-05-06 08:50:33 +000079 // var<workgroup> wg : vec4<f32>;
80 // var<workgroup> dst : vec4<f32>;
81 // fn f2(){ dst = wg; }
82 // fn f1() { f2(); }
83 // @stage(fragment)
84 // fn f0() {
85 // f1();
86 //}
Ryan Harrisondbc13af2022-02-21 15:19:07 +000087
Tint teamf4626062022-05-06 08:50:33 +000088 Global(Source{{1, 2}}, "wg", ty.vec4<f32>(), ast::StorageClass::kWorkgroup);
89 Global("dst", ty.vec4<f32>(), ast::StorageClass::kPrivate);
90 auto* stmt = Assign(Expr("dst"), Expr(Source{{3, 4}}, "wg"));
Ryan Harrisondbc13af2022-02-21 15:19:07 +000091
Tint teamf4626062022-05-06 08:50:33 +000092 Func(Source{{5, 6}}, "f2", {}, ty.void_(), {stmt});
93 Func(Source{{7, 8}}, "f1", {}, ty.void_(), {CallStmt(Call("f2"))});
94 Func(Source{{9, 10}}, "f0", {}, ty.void_(), {CallStmt(Call("f1"))},
95 ast::AttributeList{Stage(ast::PipelineStage::kFragment)});
Ryan Harrisondbc13af2022-02-21 15:19:07 +000096
Tint teamf4626062022-05-06 08:50:33 +000097 EXPECT_FALSE(r()->Resolve());
98 EXPECT_EQ(r()->error(),
99 R"(3:4 error: workgroup memory cannot be used by fragment pipeline stage
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001001:2 note: variable is declared here
1015:6 note: called by function 'f2'
1027:8 note: called by function 'f1'
1039:10 note: called by entry point 'f0')");
104}
105
106TEST_F(ResolverValidationTest, UnhandledStmt) {
Tint teamf4626062022-05-06 08:50:33 +0000107 EXPECT_FATAL_FAILURE(
108 {
109 ProgramBuilder b;
110 b.WrapInFunction(b.create<FakeStmt>());
111 Program(std::move(b));
112 },
113 "internal compiler error: unhandled node type: tint::resolver::FakeStmt");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000114}
115
116TEST_F(ResolverValidationTest, Stmt_If_NonBool) {
Tint teamf4626062022-05-06 08:50:33 +0000117 // if (1.23f) {}
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000118
Tint team2e186f22022-05-11 08:42:48 +0000119 WrapInFunction(If(Expr(Source{{12, 34}}, 1.23_f), Block()));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000120
Tint teamf4626062022-05-06 08:50:33 +0000121 EXPECT_FALSE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000122
Tint teamf4626062022-05-06 08:50:33 +0000123 EXPECT_EQ(r()->error(), "12:34 error: if statement condition must be bool, got f32");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000124}
125
Tint teamf4626062022-05-06 08:50:33 +0000126TEST_F(ResolverValidationTest, Stmt_ElseIf_NonBool) {
127 // else if (1.23f) {}
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000128
Tint team2e186f22022-05-11 08:42:48 +0000129 WrapInFunction(If(Expr(true), Block(), Else(If(Expr(Source{{12, 34}}, 1.23_f), Block()))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000130
Tint teamf4626062022-05-06 08:50:33 +0000131 EXPECT_FALSE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000132
Tint teamf4626062022-05-06 08:50:33 +0000133 EXPECT_EQ(r()->error(), "12:34 error: if statement condition must be bool, got f32");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000134}
135
136TEST_F(ResolverValidationTest, Expr_ErrUnknownExprType) {
Tint teamf4626062022-05-06 08:50:33 +0000137 EXPECT_FATAL_FAILURE(
138 {
139 ProgramBuilder b;
140 b.WrapInFunction(b.create<FakeExpr>());
141 Resolver(&b).Resolve();
142 },
143 "internal compiler error: unhandled expression type: "
144 "tint::resolver::FakeExpr");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000145}
146
147TEST_F(ResolverValidationTest, Expr_DontCall_Function) {
Tint teamf4626062022-05-06 08:50:33 +0000148 Func("func", {}, ty.void_(), {}, {});
149 WrapInFunction(Expr(Source{{{3, 3}, {3, 8}}}, "func"));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000150
Tint teamf4626062022-05-06 08:50:33 +0000151 EXPECT_FALSE(r()->Resolve());
152 EXPECT_EQ(r()->error(), "3:8 error: missing '(' for function call");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000153}
154
155TEST_F(ResolverValidationTest, Expr_DontCall_Builtin) {
Tint teamf4626062022-05-06 08:50:33 +0000156 WrapInFunction(Expr(Source{{{3, 3}, {3, 8}}}, "round"));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000157
Tint teamf4626062022-05-06 08:50:33 +0000158 EXPECT_FALSE(r()->Resolve());
159 EXPECT_EQ(r()->error(), "3:8 error: missing '(' for builtin call");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000160}
161
162TEST_F(ResolverValidationTest, Expr_DontCall_Type) {
Tint teamf4626062022-05-06 08:50:33 +0000163 Alias("T", ty.u32());
164 WrapInFunction(Expr(Source{{{3, 3}, {3, 8}}}, "T"));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000165
Tint teamf4626062022-05-06 08:50:33 +0000166 EXPECT_FALSE(r()->Resolve());
167 EXPECT_EQ(r()->error(), "3:8 error: missing '(' for type constructor or cast");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000168}
169
170TEST_F(ResolverValidationTest, AssignmentStmt_InvalidLHS_BuiltinFunctionName) {
Tint teamf4626062022-05-06 08:50:33 +0000171 // normalize = 2;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000172
Tint teamf4626062022-05-06 08:50:33 +0000173 auto* lhs = Expr(Source{{12, 34}}, "normalize");
174 auto* rhs = Expr(2_i);
175 auto* assign = Assign(lhs, rhs);
176 WrapInFunction(assign);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000177
Tint teamf4626062022-05-06 08:50:33 +0000178 EXPECT_FALSE(r()->Resolve());
179 EXPECT_EQ(r()->error(), "12:34 error: missing '(' for builtin call");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000180}
181
182TEST_F(ResolverValidationTest, UsingUndefinedVariable_Fail) {
Tint teamf4626062022-05-06 08:50:33 +0000183 // b = 2;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000184
Tint teamf4626062022-05-06 08:50:33 +0000185 auto* lhs = Expr(Source{{12, 34}}, "b");
186 auto* rhs = Expr(2_i);
187 auto* assign = Assign(lhs, rhs);
188 WrapInFunction(assign);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000189
Tint teamf4626062022-05-06 08:50:33 +0000190 EXPECT_FALSE(r()->Resolve());
191 EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'b'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000192}
193
194TEST_F(ResolverValidationTest, UsingUndefinedVariableInBlockStatement_Fail) {
Tint teamf4626062022-05-06 08:50:33 +0000195 // {
196 // b = 2;
197 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000198
Tint teamf4626062022-05-06 08:50:33 +0000199 auto* lhs = Expr(Source{{12, 34}}, "b");
200 auto* rhs = Expr(2_i);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000201
Tint teamf4626062022-05-06 08:50:33 +0000202 auto* body = Block(Assign(lhs, rhs));
203 WrapInFunction(body);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000204
Tint teamf4626062022-05-06 08:50:33 +0000205 EXPECT_FALSE(r()->Resolve());
206 EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'b'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000207}
208
209TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) {
Tint teamf4626062022-05-06 08:50:33 +0000210 // var global_var: f32 = 2.1;
211 // fn my_func() {
212 // global_var = 3.14;
213 // return;
214 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000215
Tint team2e186f22022-05-11 08:42:48 +0000216 Global("global_var", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1_f));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000217
Tint teamf4626062022-05-06 08:50:33 +0000218 Func("my_func", ast::VariableList{}, ty.void_(),
219 {
Tint team2e186f22022-05-11 08:42:48 +0000220 Assign(Expr(Source{{12, 34}}, "global_var"), 3.14_f),
Tint teamf4626062022-05-06 08:50:33 +0000221 Return(),
222 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000223
Tint teamf4626062022-05-06 08:50:33 +0000224 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000225}
226
227TEST_F(ResolverValidationTest, UsingUndefinedVariableInnerScope_Fail) {
Tint teamf4626062022-05-06 08:50:33 +0000228 // {
229 // if (true) { var a : f32 = 2.0; }
230 // a = 3.14;
231 // }
Tint team2e186f22022-05-11 08:42:48 +0000232 auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2_f));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000233
Tint teamf4626062022-05-06 08:50:33 +0000234 auto* cond = Expr(true);
235 auto* body = Block(Decl(var));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000236
Tint teamf4626062022-05-06 08:50:33 +0000237 SetSource(Source{{12, 34}});
238 auto* lhs = Expr(Source{{12, 34}}, "a");
Tint team2e186f22022-05-11 08:42:48 +0000239 auto* rhs = Expr(3.14_f);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000240
Tint teamf4626062022-05-06 08:50:33 +0000241 auto* outer_body = Block(If(cond, body), Assign(lhs, rhs));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000242
Tint teamf4626062022-05-06 08:50:33 +0000243 WrapInFunction(outer_body);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000244
Tint teamf4626062022-05-06 08:50:33 +0000245 EXPECT_FALSE(r()->Resolve());
246 EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'a'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000247}
248
249TEST_F(ResolverValidationTest, UsingUndefinedVariableOuterScope_Pass) {
Tint teamf4626062022-05-06 08:50:33 +0000250 // {
251 // var a : f32 = 2.0;
252 // if (true) { a = 3.14; }
253 // }
Tint team2e186f22022-05-11 08:42:48 +0000254 auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2_f));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000255
Tint teamf4626062022-05-06 08:50:33 +0000256 auto* lhs = Expr(Source{{12, 34}}, "a");
Tint team2e186f22022-05-11 08:42:48 +0000257 auto* rhs = Expr(3.14_f);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000258
Tint teamf4626062022-05-06 08:50:33 +0000259 auto* cond = Expr(true);
260 auto* body = Block(Assign(lhs, rhs));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000261
Tint teamf4626062022-05-06 08:50:33 +0000262 auto* outer_body = Block(Decl(var), If(cond, body));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000263
Tint teamf4626062022-05-06 08:50:33 +0000264 WrapInFunction(outer_body);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000265
Tint teamf4626062022-05-06 08:50:33 +0000266 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000267}
268
269TEST_F(ResolverValidationTest, UsingUndefinedVariableDifferentScope_Fail) {
Tint teamf4626062022-05-06 08:50:33 +0000270 // {
271 // { var a : f32 = 2.0; }
272 // { a = 3.14; }
273 // }
Tint team2e186f22022-05-11 08:42:48 +0000274 auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2_f));
Tint teamf4626062022-05-06 08:50:33 +0000275 auto* first_body = Block(Decl(var));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000276
Tint teamf4626062022-05-06 08:50:33 +0000277 auto* lhs = Expr(Source{{12, 34}}, "a");
Tint team2e186f22022-05-11 08:42:48 +0000278 auto* rhs = Expr(3.14_f);
Tint teamf4626062022-05-06 08:50:33 +0000279 auto* second_body = Block(Assign(lhs, rhs));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000280
Tint teamf4626062022-05-06 08:50:33 +0000281 auto* outer_body = Block(first_body, second_body);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000282
Tint teamf4626062022-05-06 08:50:33 +0000283 WrapInFunction(outer_body);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000284
Tint teamf4626062022-05-06 08:50:33 +0000285 EXPECT_FALSE(r()->Resolve());
286 EXPECT_EQ(r()->error(), "12:34 error: unknown identifier: 'a'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000287}
288
289TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) {
Tint teamf4626062022-05-06 08:50:33 +0000290 auto* var = Var("var", ty.i32(), ast::StorageClass::kWorkgroup);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000291
Tint teamf4626062022-05-06 08:50:33 +0000292 auto* stmt = Decl(var);
293 Func("func", ast::VariableList{}, ty.void_(), {stmt}, ast::AttributeList{});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000294
Tint teamf4626062022-05-06 08:50:33 +0000295 EXPECT_FALSE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000296
Tint teamf4626062022-05-06 08:50:33 +0000297 EXPECT_EQ(r()->error(), "error: function variable has a non-function storage class");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000298}
299
300TEST_F(ResolverValidationTest, StorageClass_FunctionVariableI32) {
Tint teamf4626062022-05-06 08:50:33 +0000301 auto* var = Var("s", ty.i32(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000302
Tint teamf4626062022-05-06 08:50:33 +0000303 auto* stmt = Decl(var);
304 Func("func", ast::VariableList{}, ty.void_(), {stmt}, ast::AttributeList{});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000305
Tint teamf4626062022-05-06 08:50:33 +0000306 EXPECT_FALSE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000307
Tint teamf4626062022-05-06 08:50:33 +0000308 EXPECT_EQ(r()->error(), "error: function variable has a non-function storage class");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000309}
310
311TEST_F(ResolverValidationTest, StorageClass_SamplerExplicitStorageClass) {
Tint teamf4626062022-05-06 08:50:33 +0000312 auto* t = ty.sampler(ast::SamplerKind::kSampler);
313 Global(Source{{12, 34}}, "var", t, ast::StorageClass::kHandle,
314 ast::AttributeList{
315 create<ast::BindingAttribute>(0),
316 create<ast::GroupAttribute>(0),
317 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000318
Tint teamf4626062022-05-06 08:50:33 +0000319 EXPECT_FALSE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000320
Tint teamf4626062022-05-06 08:50:33 +0000321 EXPECT_EQ(r()->error(),
322 R"(12:34 error: variables of type 'sampler' must not have a storage class)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000323}
324
325TEST_F(ResolverValidationTest, StorageClass_TextureExplicitStorageClass) {
Tint teamf4626062022-05-06 08:50:33 +0000326 auto* t = ty.sampled_texture(ast::TextureDimension::k1d, ty.f32());
327 Global(Source{{12, 34}}, "var", t, ast::StorageClass::kHandle,
328 ast::AttributeList{
329 create<ast::BindingAttribute>(0),
330 create<ast::GroupAttribute>(0),
331 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000332
Tint teamf4626062022-05-06 08:50:33 +0000333 EXPECT_FALSE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000334
Tint teamf4626062022-05-06 08:50:33 +0000335 EXPECT_EQ(r()->error(),
336 R"(12:34 error: variables of type 'texture_1d<f32>' must not have a storage class)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000337}
338
339TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) {
Tint teamf4626062022-05-06 08:50:33 +0000340 Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000341
Tint teamf4626062022-05-06 08:50:33 +0000342 auto* ident = Expr(Source{{{3, 3}, {3, 7}}}, "xyqz");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000343
Tint teamf4626062022-05-06 08:50:33 +0000344 auto* mem = MemberAccessor("my_vec", ident);
345 WrapInFunction(mem);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000346
Tint teamf4626062022-05-06 08:50:33 +0000347 EXPECT_FALSE(r()->Resolve());
348 EXPECT_EQ(r()->error(), "3:5 error: invalid vector swizzle character");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000349}
350
351TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) {
Tint teamf4626062022-05-06 08:50:33 +0000352 Global("my_vec", ty.vec4<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000353
Tint teamf4626062022-05-06 08:50:33 +0000354 auto* ident = Expr(Source{{{3, 3}, {3, 7}}}, "rgyw");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000355
Tint teamf4626062022-05-06 08:50:33 +0000356 auto* mem = MemberAccessor("my_vec", ident);
357 WrapInFunction(mem);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000358
Tint teamf4626062022-05-06 08:50:33 +0000359 EXPECT_FALSE(r()->Resolve());
360 EXPECT_EQ(r()->error(),
361 "3:3 error: invalid mixing of vector swizzle characters rgba with xyzw");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000362}
363
364TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) {
Tint teamf4626062022-05-06 08:50:33 +0000365 Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000366
Tint teamf4626062022-05-06 08:50:33 +0000367 auto* ident = Expr(Source{{{3, 3}, {3, 8}}}, "zzzzz");
368 auto* mem = MemberAccessor("my_vec", ident);
369 WrapInFunction(mem);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000370
Tint teamf4626062022-05-06 08:50:33 +0000371 EXPECT_FALSE(r()->Resolve());
372 EXPECT_EQ(r()->error(), "3:3 error: invalid vector swizzle size");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000373}
374
375TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadIndex) {
Tint teamf4626062022-05-06 08:50:33 +0000376 Global("my_vec", ty.vec2<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000377
Tint teamf4626062022-05-06 08:50:33 +0000378 auto* ident = Expr(Source{{3, 3}}, "z");
379 auto* mem = MemberAccessor("my_vec", ident);
380 WrapInFunction(mem);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000381
Tint teamf4626062022-05-06 08:50:33 +0000382 EXPECT_FALSE(r()->Resolve());
383 EXPECT_EQ(r()->error(), "3:3 error: invalid vector swizzle member");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000384}
385
386TEST_F(ResolverValidationTest, Expr_MemberAccessor_BadParent) {
Tint teamf4626062022-05-06 08:50:33 +0000387 // var param: vec4<f32>
388 // let ret: f32 = *(&param).x;
389 auto* param = Var("param", ty.vec4<f32>());
390 auto* x = Expr(Source{{{3, 3}, {3, 8}}}, "x");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000391
Tint teamf4626062022-05-06 08:50:33 +0000392 auto* addressOf_expr = AddressOf(Source{{12, 34}}, param);
393 auto* accessor_expr = MemberAccessor(addressOf_expr, x);
394 auto* star_p = Deref(accessor_expr);
395 auto* ret = Var("r", ty.f32(), star_p);
396 WrapInFunction(Decl(param), Decl(ret));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000397
Tint teamf4626062022-05-06 08:50:33 +0000398 EXPECT_FALSE(r()->Resolve());
399 EXPECT_EQ(r()->error(),
400 "12:34 error: invalid member accessor expression. Expected vector "
401 "or struct, got 'ptr<function, vec4<f32>, read_write>'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000402}
403
404TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncGoodParent) {
Tint teamf4626062022-05-06 08:50:33 +0000405 // fn func(p: ptr<function, vec4<f32>>) -> f32 {
406 // let x: f32 = (*p).z;
407 // return x;
408 // }
409 auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
410 auto* star_p = Deref(p);
411 auto* z = Expr(Source{{{3, 3}, {3, 8}}}, "z");
412 auto* accessor_expr = MemberAccessor(star_p, z);
413 auto* x = Var("x", ty.f32(), accessor_expr);
414 Func("func", {p}, ty.f32(), {Decl(x), Return(x)});
415 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000416}
417
418TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncBadParent) {
Tint teamf4626062022-05-06 08:50:33 +0000419 // fn func(p: ptr<function, vec4<f32>>) -> f32 {
420 // let x: f32 = *p.z;
421 // return x;
422 // }
423 auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
424 auto* z = Expr(Source{{{3, 3}, {3, 8}}}, "z");
425 auto* accessor_expr = MemberAccessor(p, z);
426 auto* star_p = Deref(accessor_expr);
427 auto* x = Var("x", ty.f32(), star_p);
428 Func("func", {p}, ty.f32(), {Decl(x), Return(x)});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000429
Tint teamf4626062022-05-06 08:50:33 +0000430 EXPECT_FALSE(r()->Resolve());
431 EXPECT_EQ(r()->error(),
432 "error: invalid member accessor expression. "
433 "Expected vector or struct, got 'ptr<function, vec4<f32>, read_write>'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000434}
435
436TEST_F(ResolverValidationTest,
437 Stmt_Loop_ContinueInLoopBodyBeforeDeclAndAfterDecl_UsageInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +0000438 // loop {
439 // continue; // Bypasses z decl
440 // var z : i32; // unreachable
441 //
442 // continuing {
443 // z = 2;
444 // }
445 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000446
Tint teamf4626062022-05-06 08:50:33 +0000447 auto error_loc = Source{{12, 34}};
448 auto* body = Block(Continue(), Decl(error_loc, Var("z", ty.i32(), ast::StorageClass::kNone)));
449 auto* continuing = Block(Assign(Expr("z"), 2_i));
450 auto* loop_stmt = Loop(body, continuing);
451 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000452
Tint teamf4626062022-05-06 08:50:33 +0000453 EXPECT_FALSE(r()->Resolve());
454 EXPECT_EQ(r()->error(),
455 R"(12:34 warning: code is unreachable
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000456error: continue statement bypasses declaration of 'z'
457note: identifier 'z' declared here
458note: identifier 'z' referenced in continuing block here)");
459}
460
Tint teamf4626062022-05-06 08:50:33 +0000461TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInLoopBodyAfterDecl_UsageInContinuing_InBlocks) {
462 // loop {
463 // if (false) { break; }
464 // var z : i32;
465 // {{{continue;}}}
466 // continue; // Ok
467 //
468 // continuing {
469 // z = 2i;
470 // }
471 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000472
Tint teamf4626062022-05-06 08:50:33 +0000473 auto* body =
474 Block(If(false, Block(Break())), //
475 Decl(Var("z", ty.i32(), ast::StorageClass::kNone)), Block(Block(Block(Continue()))));
476 auto* continuing = Block(Assign(Expr("z"), 2_i));
477 auto* loop_stmt = Loop(body, continuing);
478 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000479
Tint teamf4626062022-05-06 08:50:33 +0000480 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000481}
482
Tint teamf4626062022-05-06 08:50:33 +0000483TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageInContinuing) {
484 // loop {
485 // if (true) {
486 // continue; // Still bypasses z decl (if we reach here)
487 // }
488 // var z : i32;
489 // continuing {
490 // z = 2i;
491 // }
492 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000493
Tint teamf4626062022-05-06 08:50:33 +0000494 auto cont_loc = Source{{12, 34}};
495 auto decl_loc = Source{{56, 78}};
496 auto ref_loc = Source{{90, 12}};
497 auto* body = Block(If(Expr(true), Block(Continue(cont_loc))),
498 Decl(Var(decl_loc, "z", ty.i32(), ast::StorageClass::kNone)));
499 auto* continuing = Block(Assign(Expr(ref_loc, "z"), 2_i));
500 auto* loop_stmt = Loop(body, continuing);
501 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000502
Tint teamf4626062022-05-06 08:50:33 +0000503 EXPECT_FALSE(r()->Resolve()) << r()->error();
504 EXPECT_EQ(r()->error(),
505 R"(12:34 error: continue statement bypasses declaration of 'z'
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050656:78 note: identifier 'z' declared here
50790:12 note: identifier 'z' referenced in continuing block here)");
508}
509
510TEST_F(ResolverValidationTest,
Tint teamf4626062022-05-06 08:50:33 +0000511 Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageInContinuingSubscope) {
512 // loop {
513 // if (true) {
514 // continue; // Still bypasses z decl (if we reach here)
515 // }
516 // var z : i32;
517 // continuing {
518 // if (true) {
519 // z = 2i; // Must fail even if z is in a sub-scope
520 // }
521 // }
522 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000523
Tint teamf4626062022-05-06 08:50:33 +0000524 auto cont_loc = Source{{12, 34}};
525 auto decl_loc = Source{{56, 78}};
526 auto ref_loc = Source{{90, 12}};
527 auto* body = Block(If(Expr(true), Block(Continue(cont_loc))),
528 Decl(Var(decl_loc, "z", ty.i32(), ast::StorageClass::kNone)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000529
Tint teamf4626062022-05-06 08:50:33 +0000530 auto* continuing = Block(If(Expr(true), Block(Assign(Expr(ref_loc, "z"), 2_i))));
531 auto* loop_stmt = Loop(body, continuing);
532 WrapInFunction(loop_stmt);
533
534 EXPECT_FALSE(r()->Resolve()) << r()->error();
535 EXPECT_EQ(r()->error(),
536 R"(12:34 error: continue statement bypasses declaration of 'z'
53756:78 note: identifier 'z' declared here
53890:12 note: identifier 'z' referenced in continuing block here)");
539}
540
541TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageOutsideBlock) {
542 // loop {
543 // if (true) {
544 // continue; // bypasses z decl (if we reach here)
545 // }
546 // var z : i32;
547 // continuing {
548 // // Must fail even if z is used in an expression that isn't
549 // // directly contained inside a block.
550 // if (z < 2i) {
551 // }
552 // }
553 // }
554
555 auto cont_loc = Source{{12, 34}};
556 auto decl_loc = Source{{56, 78}};
557 auto ref_loc = Source{{90, 12}};
558 auto* body = Block(If(Expr(true), Block(Continue(cont_loc))),
559 Decl(Var(decl_loc, "z", ty.i32(), ast::StorageClass::kNone)));
560 auto* compare =
561 create<ast::BinaryExpression>(ast::BinaryOp::kLessThan, Expr(ref_loc, "z"), Expr(2_i));
562 auto* continuing = Block(If(compare, Block()));
563 auto* loop_stmt = Loop(body, continuing);
564 WrapInFunction(loop_stmt);
565
566 EXPECT_FALSE(r()->Resolve()) << r()->error();
567 EXPECT_EQ(r()->error(),
568 R"(12:34 error: continue statement bypasses declaration of 'z'
Ryan Harrisondbc13af2022-02-21 15:19:07 +000056956:78 note: identifier 'z' declared here
57090:12 note: identifier 'z' referenced in continuing block here)");
571}
572
573TEST_F(ResolverValidationTest,
574 Stmt_Loop_ContinueInLoopBodySubscopeBeforeDecl_UsageInContinuingLoop) {
Tint teamf4626062022-05-06 08:50:33 +0000575 // loop {
576 // if (true) {
577 // continue; // Still bypasses z decl (if we reach here)
578 // }
579 // var z : i32;
580 // continuing {
581 // loop {
582 // z = 2i; // Must fail even if z is in a sub-scope
583 // }
584 // }
585 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000586
Tint teamf4626062022-05-06 08:50:33 +0000587 auto cont_loc = Source{{12, 34}};
588 auto decl_loc = Source{{56, 78}};
589 auto ref_loc = Source{{90, 12}};
590 auto* body = Block(If(Expr(true), Block(Continue(cont_loc))),
591 Decl(Var(decl_loc, "z", ty.i32(), ast::StorageClass::kNone)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000592
Tint teamf4626062022-05-06 08:50:33 +0000593 auto* continuing = Block(Loop(Block(Assign(Expr(ref_loc, "z"), 2_i))));
594 auto* loop_stmt = Loop(body, continuing);
595 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000596
Tint teamf4626062022-05-06 08:50:33 +0000597 EXPECT_FALSE(r()->Resolve()) << r()->error();
598 EXPECT_EQ(r()->error(),
599 R"(12:34 error: continue statement bypasses declaration of 'z'
Ryan Harrisondbc13af2022-02-21 15:19:07 +000060056:78 note: identifier 'z' declared here
60190:12 note: identifier 'z' referenced in continuing block here)");
602}
603
Tint teamf4626062022-05-06 08:50:33 +0000604TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInNestedLoopBodyBeforeDecl_UsageInContinuing) {
605 // loop {
606 // loop {
607 // if (true) { continue; } // OK: not part of the outer loop
608 // break;
609 // }
610 // var z : i32;
611 // break;
612 // continuing {
613 // z = 2i;
614 // }
615 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000616
Tint teamf4626062022-05-06 08:50:33 +0000617 auto* inner_loop = Loop(Block( //
618 If(true, Block(Continue())), //
619 Break()));
620 auto* body = Block(inner_loop, //
621 Decl(Var("z", ty.i32(), ast::StorageClass::kNone)), //
622 Break());
623 auto* continuing = Block(Assign("z", 2_i));
624 auto* loop_stmt = Loop(body, continuing);
625 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000626
Tint teamf4626062022-05-06 08:50:33 +0000627 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000628}
629
630TEST_F(ResolverValidationTest,
631 Stmt_Loop_ContinueInNestedLoopBodyBeforeDecl_UsageInContinuingSubscope) {
Tint teamf4626062022-05-06 08:50:33 +0000632 // loop {
633 // loop {
634 // if (true) { continue; } // OK: not part of the outer loop
635 // break;
636 // }
637 // var z : i32;
638 // break;
639 // continuing {
640 // if (true) {
641 // z = 2i;
642 // }
643 // }
644 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000645
Tint teamf4626062022-05-06 08:50:33 +0000646 auto* inner_loop = Loop(Block(If(true, Block(Continue())), //
647 Break()));
648 auto* body = Block(inner_loop, //
649 Decl(Var("z", ty.i32(), ast::StorageClass::kNone)), //
650 Break());
651 auto* continuing = Block(If(Expr(true), Block(Assign("z", 2_i))));
652 auto* loop_stmt = Loop(body, continuing);
653 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000654
Tint teamf4626062022-05-06 08:50:33 +0000655 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000656}
657
Tint teamf4626062022-05-06 08:50:33 +0000658TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInNestedLoopBodyBeforeDecl_UsageInContinuingLoop) {
659 // loop {
660 // loop {
661 // if (true) { continue; } // OK: not part of the outer loop
662 // break;
663 // }
664 // var z : i32;
665 // break;
666 // continuing {
667 // loop {
668 // z = 2i;
669 // break;
670 // }
671 // }
672 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000673
Tint teamf4626062022-05-06 08:50:33 +0000674 auto* inner_loop = Loop(Block(If(true, Block(Continue())), //
675 Break()));
676 auto* body = Block(inner_loop, //
677 Decl(Var("z", ty.i32(), ast::StorageClass::kNone)), //
678 Break());
679 auto* continuing = Block(Loop(Block(Assign("z", 2_i), //
680 Break())));
681 auto* loop_stmt = Loop(body, continuing);
682 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000683
Tint teamf4626062022-05-06 08:50:33 +0000684 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000685}
686
687TEST_F(ResolverTest, Stmt_Loop_ContinueInLoopBodyAfterDecl_UsageInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +0000688 // loop {
689 // var z : i32;
690 // if (true) { continue; }
691 // break;
692 // continuing {
693 // z = 2i;
694 // }
695 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000696
Tint teamf4626062022-05-06 08:50:33 +0000697 auto error_loc = Source{{12, 34}};
698 auto* body =
699 Block(Decl(Var("z", ty.i32(), ast::StorageClass::kNone)), If(true, Block(Continue())), //
700 Break());
701 auto* continuing = Block(Assign(Expr(error_loc, "z"), 2_i));
702 auto* loop_stmt = Loop(body, continuing);
703 WrapInFunction(loop_stmt);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000704
Tint teamf4626062022-05-06 08:50:33 +0000705 EXPECT_TRUE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000706}
707
708TEST_F(ResolverTest, Stmt_Loop_ReturnInContinuing_Direct) {
Tint teamf4626062022-05-06 08:50:33 +0000709 // loop {
710 // continuing {
711 // return;
712 // }
713 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000714
Tint teamf4626062022-05-06 08:50:33 +0000715 WrapInFunction(Loop( // loop
716 Block(), // loop block
717 Block( // loop continuing block
718 Return(Source{{12, 34}}))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000719
Tint teamf4626062022-05-06 08:50:33 +0000720 EXPECT_FALSE(r()->Resolve());
721 EXPECT_EQ(r()->error(),
722 R"(12:34 error: continuing blocks must not contain a return statement)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000723}
724
725TEST_F(ResolverTest, Stmt_Loop_ReturnInContinuing_Indirect) {
Tint teamf4626062022-05-06 08:50:33 +0000726 // loop {
727 // if (false) { break; }
728 // continuing {
729 // loop {
730 // return;
731 // }
732 // }
733 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000734
Tint teamf4626062022-05-06 08:50:33 +0000735 WrapInFunction(Loop( // outer loop
736 Block(If(false, Block(Break()))), // outer loop block
737 Block(Source{{56, 78}}, // outer loop continuing block
738 Loop( // inner loop
739 Block( // inner loop block
740 Return(Source{{12, 34}}))))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000741
Tint teamf4626062022-05-06 08:50:33 +0000742 EXPECT_FALSE(r()->Resolve());
743 EXPECT_EQ(r()->error(),
744 R"(12:34 error: continuing blocks must not contain a return statement
Ryan Harrisondbc13af2022-02-21 15:19:07 +000074556:78 note: see continuing block here)");
746}
747
748TEST_F(ResolverTest, Stmt_Loop_DiscardInContinuing_Direct) {
Tint teamf4626062022-05-06 08:50:33 +0000749 // loop {
750 // continuing {
751 // discard;
752 // }
753 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000754
Tint teamf4626062022-05-06 08:50:33 +0000755 WrapInFunction(Loop( // loop
756 Block(), // loop block
757 Block( // loop continuing block
758 Discard(Source{{12, 34}}))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000759
Tint teamf4626062022-05-06 08:50:33 +0000760 EXPECT_FALSE(r()->Resolve());
761 EXPECT_EQ(r()->error(),
762 R"(12:34 error: continuing blocks must not contain a discard statement)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000763}
764
765TEST_F(ResolverTest, Stmt_Loop_DiscardInContinuing_Indirect) {
Tint teamf4626062022-05-06 08:50:33 +0000766 // loop {
767 // if (false) { break; }
768 // continuing {
769 // loop { discard; }
770 // }
771 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000772
Tint teamf4626062022-05-06 08:50:33 +0000773 WrapInFunction(Loop( // outer loop
774 Block(If(false, Block(Break()))), // outer loop block
775 Block(Source{{56, 78}}, // outer loop continuing block
776 Loop( // inner loop
777 Block( // inner loop block
778 Discard(Source{{12, 34}}))))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000779
Tint teamf4626062022-05-06 08:50:33 +0000780 EXPECT_FALSE(r()->Resolve());
781 EXPECT_EQ(r()->error(),
782 R"(12:34 error: continuing blocks must not contain a discard statement
Ryan Harrisondbc13af2022-02-21 15:19:07 +000078356:78 note: see continuing block here)");
784}
785
786TEST_F(ResolverTest, Stmt_Loop_DiscardInContinuing_Indirect_ViaCall) {
Tint teamf4626062022-05-06 08:50:33 +0000787 // fn MayDiscard() { if (true) { discard; } }
788 // fn F() { MayDiscard(); }
789 // loop {
790 // continuing {
791 // loop { F(); }
792 // }
793 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000794
Tint teamf4626062022-05-06 08:50:33 +0000795 Func("MayDiscard", {}, ty.void_(), {If(true, Block(Discard()))});
796 Func("SomeFunc", {}, ty.void_(), {CallStmt(Call("MayDiscard"))});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000797
Tint teamf4626062022-05-06 08:50:33 +0000798 WrapInFunction(Loop( // outer loop
799 Block(), // outer loop block
800 Block(Source{{56, 78}}, // outer loop continuing block
801 Loop( // inner loop
802 Block( // inner loop block
803 CallStmt(Call(Source{{12, 34}}, "SomeFunc")))))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000804
Tint teamf4626062022-05-06 08:50:33 +0000805 EXPECT_FALSE(r()->Resolve());
806 EXPECT_EQ(r()->error(),
807 R"(12:34 error: cannot call a function that may discard inside a continuing block
Ryan Harrisondbc13af2022-02-21 15:19:07 +000080856:78 note: see continuing block here)");
809}
810
811TEST_F(ResolverTest, Stmt_Loop_ContinueInContinuing_Direct) {
Tint teamf4626062022-05-06 08:50:33 +0000812 // loop {
813 // continuing {
814 // continue;
815 // }
816 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000817
Tint teamf4626062022-05-06 08:50:33 +0000818 WrapInFunction(Loop( // loop
819 Block(), // loop block
820 Block(Source{{56, 78}}, // loop continuing block
821 Continue(Source{{12, 34}}))));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000822
Tint teamf4626062022-05-06 08:50:33 +0000823 EXPECT_FALSE(r()->Resolve());
824 EXPECT_EQ(r()->error(), "12:34 error: continuing blocks must not contain a continue statement");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000825}
826
827TEST_F(ResolverTest, Stmt_Loop_ContinueInContinuing_Indirect) {
Tint teamf4626062022-05-06 08:50:33 +0000828 // loop {
829 // if (false) { break; }
830 // continuing {
831 // loop {
832 // if (false) { break; }
833 // continue;
834 // }
835 // }
836 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000837
Tint teamf4626062022-05-06 08:50:33 +0000838 WrapInFunction(Loop( // outer loop
839 Block( // outer loop block
840 If(false, Block(Break()))), // if (false) { break; }
841 Block( // outer loop continuing block
842 Loop( // inner loop
843 Block( // inner loop block
844 If(false, Block(Break())), // if (false) { break; }
845 Continue(Source{{12, 34}})))))); // continue
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000846
Tint teamf4626062022-05-06 08:50:33 +0000847 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000848}
849
850TEST_F(ResolverTest, Stmt_ForLoop_ReturnInContinuing_Direct) {
Tint teamf4626062022-05-06 08:50:33 +0000851 // for(;; return) {
852 // break;
853 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000854
Tint teamf4626062022-05-06 08:50:33 +0000855 WrapInFunction(For(nullptr, nullptr, Return(Source{{12, 34}}), //
856 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000857
Tint teamf4626062022-05-06 08:50:33 +0000858 EXPECT_FALSE(r()->Resolve());
859 EXPECT_EQ(r()->error(),
860 R"(12:34 error: continuing blocks must not contain a return statement)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000861}
862
863TEST_F(ResolverTest, Stmt_ForLoop_ReturnInContinuing_Indirect) {
Tint teamf4626062022-05-06 08:50:33 +0000864 // for(;; loop { return }) {
865 // break;
866 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000867
Tint teamf4626062022-05-06 08:50:33 +0000868 WrapInFunction(For(nullptr, nullptr,
869 Loop(Source{{56, 78}}, //
870 Block(Return(Source{{12, 34}}))), //
871 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000872
Tint teamf4626062022-05-06 08:50:33 +0000873 EXPECT_FALSE(r()->Resolve());
874 EXPECT_EQ(r()->error(),
875 R"(12:34 error: continuing blocks must not contain a return statement
Ryan Harrisondbc13af2022-02-21 15:19:07 +000087656:78 note: see continuing block here)");
877}
878
879TEST_F(ResolverTest, Stmt_ForLoop_DiscardInContinuing_Direct) {
Tint teamf4626062022-05-06 08:50:33 +0000880 // for(;; discard) {
881 // break;
882 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000883
Tint teamf4626062022-05-06 08:50:33 +0000884 WrapInFunction(For(nullptr, nullptr, Discard(Source{{12, 34}}), //
885 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000886
Tint teamf4626062022-05-06 08:50:33 +0000887 EXPECT_FALSE(r()->Resolve());
888 EXPECT_EQ(r()->error(),
889 R"(12:34 error: continuing blocks must not contain a discard statement)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000890}
891
892TEST_F(ResolverTest, Stmt_ForLoop_DiscardInContinuing_Indirect) {
Tint teamf4626062022-05-06 08:50:33 +0000893 // for(;; loop { discard }) {
894 // break;
895 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000896
Tint teamf4626062022-05-06 08:50:33 +0000897 WrapInFunction(For(nullptr, nullptr,
898 Loop(Source{{56, 78}}, //
899 Block(Discard(Source{{12, 34}}))), //
900 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000901
Tint teamf4626062022-05-06 08:50:33 +0000902 EXPECT_FALSE(r()->Resolve());
903 EXPECT_EQ(r()->error(),
904 R"(12:34 error: continuing blocks must not contain a discard statement
Ryan Harrisondbc13af2022-02-21 15:19:07 +000090556:78 note: see continuing block here)");
906}
907
908TEST_F(ResolverTest, Stmt_ForLoop_DiscardInContinuing_Indirect_ViaCall) {
Tint teamf4626062022-05-06 08:50:33 +0000909 // fn MayDiscard() { if (true) { discard; } }
910 // fn F() { MayDiscard(); }
911 // for(;; loop { F() }) {
912 // break;
913 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000914
Tint teamf4626062022-05-06 08:50:33 +0000915 Func("MayDiscard", {}, ty.void_(), {If(true, Block(Discard()))});
916 Func("F", {}, ty.void_(), {CallStmt(Call("MayDiscard"))});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000917
Tint teamf4626062022-05-06 08:50:33 +0000918 WrapInFunction(For(nullptr, nullptr,
919 Loop(Source{{56, 78}}, //
920 Block(CallStmt(Call(Source{{12, 34}}, "F")))), //
921 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000922
Tint teamf4626062022-05-06 08:50:33 +0000923 EXPECT_FALSE(r()->Resolve());
924 EXPECT_EQ(r()->error(),
925 R"(12:34 error: cannot call a function that may discard inside a continuing block
Ryan Harrisondbc13af2022-02-21 15:19:07 +000092656:78 note: see continuing block here)");
927}
928
929TEST_F(ResolverTest, Stmt_ForLoop_ContinueInContinuing_Direct) {
Tint teamf4626062022-05-06 08:50:33 +0000930 // for(;; continue) {
931 // break;
932 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000933
Tint teamf4626062022-05-06 08:50:33 +0000934 WrapInFunction(For(nullptr, nullptr, Continue(Source{{12, 34}}), //
935 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000936
Tint teamf4626062022-05-06 08:50:33 +0000937 EXPECT_FALSE(r()->Resolve());
938 EXPECT_EQ(r()->error(), "12:34 error: continuing blocks must not contain a continue statement");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000939}
940
941TEST_F(ResolverTest, Stmt_ForLoop_ContinueInContinuing_Indirect) {
Tint teamf4626062022-05-06 08:50:33 +0000942 // for(;; loop { if (false) { break; } continue }) {
943 // break;
944 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000945
Tint teamf4626062022-05-06 08:50:33 +0000946 WrapInFunction(For(nullptr, nullptr,
947 Loop( //
948 Block(If(false, Block(Break())), //
949 Continue(Source{{12, 34}}))), //
950 Block(Break())));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000951
Tint teamf4626062022-05-06 08:50:33 +0000952 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000953}
954
955TEST_F(ResolverTest, Stmt_ForLoop_CondIsBoolRef) {
Tint teamf4626062022-05-06 08:50:33 +0000956 // var cond : bool = true;
957 // for (; cond; ) {
958 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000959
Tint teamf4626062022-05-06 08:50:33 +0000960 auto* cond = Var("cond", ty.bool_(), Expr(true));
961 WrapInFunction(Decl(cond), For(nullptr, "cond", nullptr, Block()));
962 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000963}
964
965TEST_F(ResolverTest, Stmt_ForLoop_CondIsNotBool) {
Tint teamf4626062022-05-06 08:50:33 +0000966 // for (; 1.0f; ) {
967 // }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000968
Tint team2e186f22022-05-11 08:42:48 +0000969 WrapInFunction(For(nullptr, Expr(Source{{12, 34}}, 1_f), nullptr, Block()));
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000970
Tint teamf4626062022-05-06 08:50:33 +0000971 EXPECT_FALSE(r()->Resolve());
972 EXPECT_EQ(r()->error(), "12:34 error: for-loop condition must be bool, got f32");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000973}
974
975TEST_F(ResolverValidationTest, Stmt_ContinueInLoop) {
Tint teamf4626062022-05-06 08:50:33 +0000976 WrapInFunction(Loop(Block(If(false, Block(Break())), //
977 Continue(Source{{12, 34}}))));
978 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000979}
980
981TEST_F(ResolverValidationTest, Stmt_ContinueNotInLoop) {
Tint teamf4626062022-05-06 08:50:33 +0000982 WrapInFunction(Continue(Source{{12, 34}}));
983 EXPECT_FALSE(r()->Resolve());
984 EXPECT_EQ(r()->error(), "12:34 error: continue statement must be in a loop");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000985}
986
987TEST_F(ResolverValidationTest, Stmt_BreakInLoop) {
Tint teamf4626062022-05-06 08:50:33 +0000988 WrapInFunction(Loop(Block(Break(Source{{12, 34}}))));
989 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000990}
991
992TEST_F(ResolverValidationTest, Stmt_BreakInSwitch) {
Tint teamf4626062022-05-06 08:50:33 +0000993 WrapInFunction(Loop(Block(Switch(Expr(1_i), //
994 Case(Expr(1_i), //
995 Block(Break())), //
996 DefaultCase()), //
997 Break()))); //
998 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000999}
1000
1001TEST_F(ResolverValidationTest, Stmt_BreakInIfTrueInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +00001002 auto* cont = Block( // continuing {
1003 If(true, Block( // if(true) {
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001004 Break(Source{{12, 34}})))); // break;
1005 // }
1006 // }
Tint teamf4626062022-05-06 08:50:33 +00001007 WrapInFunction(Loop(Block(), cont));
1008 EXPECT_TRUE(r()->Resolve()) << r()->error();
1009}
1010
1011TEST_F(ResolverValidationTest, Stmt_BreakInIfElseInContinuing) {
1012 auto* cont = Block( // continuing {
1013 If(true, Block(), // if(true) {
1014 Else(Block( // } else {
1015 Break(Source{{12, 34}}))))); // break;
1016 // }
1017 // }
1018 WrapInFunction(Loop(Block(), cont));
1019 EXPECT_TRUE(r()->Resolve()) << r()->error();
1020}
1021
1022TEST_F(ResolverValidationTest, Stmt_BreakInContinuing) {
1023 auto* cont = Block( // continuing {
1024 Block(Break(Source{{12, 34}}))); // break;
1025 // }
1026 WrapInFunction(Loop(Block(), cont));
1027 EXPECT_FALSE(r()->Resolve());
1028 EXPECT_EQ(r()->error(),
1029 "12:34 error: break statement in a continuing block must be the single "
1030 "statement of an if statement's true or false block, and that if "
1031 "statement must be the last statement of the continuing block\n"
1032 "12:34 note: break statement is not directly in if statement block");
1033}
1034
1035TEST_F(ResolverValidationTest, Stmt_BreakInIfInIfInContinuing) {
1036 auto* cont = Block( // continuing {
1037 If(true, Block( // if(true) {
1038 If(Source{{56, 78}}, true, // if(true) {
1039 Block(Break(Source{{12, 34}})))))); // break;
1040 // }
1041 // }
1042 // }
1043 WrapInFunction(Loop(Block(), cont));
1044 EXPECT_FALSE(r()->Resolve());
1045 EXPECT_EQ(r()->error(),
1046 "12:34 error: break statement in a continuing block must be the single "
1047 "statement of an if statement's true or false block, and that if "
1048 "statement must be the last statement of the continuing block\n"
1049 "56:78 note: if statement containing break statement is not directly in "
1050 "continuing block");
1051}
1052
1053TEST_F(ResolverValidationTest, Stmt_BreakInIfTrueMultipleStmtsInContinuing) {
1054 auto* cont = Block( // continuing {
1055 If(true, Block(Source{{56, 78}}, // if(true) {
1056 Assign(Phony(), 1_i), // _ = 1i;
1057 Break(Source{{12, 34}})))); // break;
1058 // }
1059 // }
1060 WrapInFunction(Loop(Block(), cont));
1061 EXPECT_FALSE(r()->Resolve());
1062 EXPECT_EQ(r()->error(),
1063 "12:34 error: break statement in a continuing block must be the single "
1064 "statement of an if statement's true or false block, and that if "
1065 "statement must be the last statement of the continuing block\n"
1066 "56:78 note: if statement block contains multiple statements");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001067}
1068
1069TEST_F(ResolverValidationTest, Stmt_BreakInIfElseMultipleStmtsInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +00001070 auto* cont = Block( // continuing {
1071 If(true, Block(), // if(true) {
1072 Else(Block(Source{{56, 78}}, // } else {
1073 Assign(Phony(), 1_i), // _ = 1i;
1074 Break(Source{{12, 34}}))))); // break;
1075 // }
1076 // }
1077 WrapInFunction(Loop(Block(), cont));
1078 EXPECT_FALSE(r()->Resolve());
1079 EXPECT_EQ(r()->error(),
1080 "12:34 error: break statement in a continuing block must be the single "
1081 "statement of an if statement's true or false block, and that if "
1082 "statement must be the last statement of the continuing block\n"
1083 "56:78 note: if statement block contains multiple statements");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001084}
1085
1086TEST_F(ResolverValidationTest, Stmt_BreakInIfElseIfInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +00001087 auto* cont = Block( // continuing {
1088 If(true, Block(), // if(true) {
1089 Else(If(Source{{56, 78}}, Expr(true), // } else if (true) {
1090 Block(Break(Source{{12, 34}})))))); // break;
1091 // }
1092 // }
1093 WrapInFunction(Loop(Block(), cont));
1094 EXPECT_FALSE(r()->Resolve());
1095 EXPECT_EQ(r()->error(),
1096 "12:34 error: break statement in a continuing block must be the single "
1097 "statement of an if statement's true or false block, and that if "
1098 "statement must be the last statement of the continuing block\n"
1099 "56:78 note: else has condition");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001100}
1101
1102TEST_F(ResolverValidationTest, Stmt_BreakInIfNonEmptyElseInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +00001103 auto* cont = Block( // continuing {
1104 If(true, // if(true) {
1105 Block(Break(Source{{12, 34}})), // break;
1106 Else(Block(Source{{56, 78}}, // } else {
1107 Assign(Phony(), 1_i))))); // _ = 1i;
1108 // }
1109 // }
1110 WrapInFunction(Loop(Block(), cont));
1111 EXPECT_FALSE(r()->Resolve());
1112 EXPECT_EQ(r()->error(),
1113 "12:34 error: break statement in a continuing block must be the single "
1114 "statement of an if statement's true or false block, and that if "
1115 "statement must be the last statement of the continuing block\n"
1116 "56:78 note: non-empty false block");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001117}
1118
1119TEST_F(ResolverValidationTest, Stmt_BreakInIfElseNonEmptyTrueInContinuing) {
Tint teamf4626062022-05-06 08:50:33 +00001120 auto* cont = Block( // continuing {
1121 If(true, // if(true) {
1122 Block(Source{{56, 78}}, Assign(Phony(), 1_i)), // _ = 1i;
1123 Else(Block( // } else {
1124 Break(Source{{12, 34}}))))); // break;
1125 // }
1126 // }
1127 WrapInFunction(Loop(Block(), cont));
1128 EXPECT_FALSE(r()->Resolve());
1129 EXPECT_EQ(r()->error(),
1130 "12:34 error: break statement in a continuing block must be the single "
1131 "statement of an if statement's true or false block, and that if "
1132 "statement must be the last statement of the continuing block\n"
1133 "56:78 note: non-empty true block");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001134}
1135
1136TEST_F(ResolverValidationTest, Stmt_BreakInIfInContinuingNotLast) {
Tint teamf4626062022-05-06 08:50:33 +00001137 auto* cont = Block( // continuing {
1138 If(Source{{56, 78}}, true, // if(true) {
1139 Block(Break(Source{{12, 34}}))), // break;
1140 // }
1141 Assign(Phony(), 1_i)); // _ = 1i;
1142 // }
1143 WrapInFunction(Loop(Block(), cont));
1144 EXPECT_FALSE(r()->Resolve());
1145 EXPECT_EQ(r()->error(),
1146 "12:34 error: break statement in a continuing block must be the single "
1147 "statement of an if statement's true or false block, and that if "
1148 "statement must be the last statement of the continuing block\n"
1149 "56:78 note: if statement containing break statement is not the last "
1150 "statement of the continuing block");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001151}
1152
1153TEST_F(ResolverValidationTest, Stmt_BreakNotInLoopOrSwitch) {
Tint teamf4626062022-05-06 08:50:33 +00001154 WrapInFunction(Break(Source{{12, 34}}));
1155 EXPECT_FALSE(r()->Resolve());
1156 EXPECT_EQ(r()->error(), "12:34 error: break statement must be in a loop or switch case");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001157}
1158
1159TEST_F(ResolverValidationTest, StructMemberDuplicateName) {
Tint teamf4626062022-05-06 08:50:33 +00001160 Structure("S",
1161 {Member(Source{{12, 34}}, "a", ty.i32()), Member(Source{{56, 78}}, "a", ty.i32())});
1162 EXPECT_FALSE(r()->Resolve());
1163 EXPECT_EQ(r()->error(),
1164 "56:78 error: redefinition of 'a'\n12:34 note: previous definition "
1165 "is here");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001166}
1167TEST_F(ResolverValidationTest, StructMemberDuplicateNameDifferentTypes) {
Tint teamf4626062022-05-06 08:50:33 +00001168 Structure("S", {Member(Source{{12, 34}}, "a", ty.bool_()),
1169 Member(Source{{12, 34}}, "a", ty.vec3<f32>())});
1170 EXPECT_FALSE(r()->Resolve());
1171 EXPECT_EQ(r()->error(),
1172 "12:34 error: redefinition of 'a'\n12:34 note: previous definition "
1173 "is here");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001174}
1175TEST_F(ResolverValidationTest, StructMemberDuplicateNamePass) {
Tint teamf4626062022-05-06 08:50:33 +00001176 Structure("S", {Member("a", ty.i32()), Member("b", ty.f32())});
1177 Structure("S1", {Member("a", ty.i32()), Member("b", ty.f32())});
1178 EXPECT_TRUE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001179}
1180
1181TEST_F(ResolverValidationTest, NonPOTStructMemberAlignAttribute) {
Tint teamf4626062022-05-06 08:50:33 +00001182 Structure("S", {
1183 Member("a", ty.f32(), {MemberAlign(Source{{12, 34}}, 3)}),
1184 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001185
Tint teamf4626062022-05-06 08:50:33 +00001186 EXPECT_FALSE(r()->Resolve());
1187 EXPECT_EQ(r()->error(), "12:34 error: align value must be a positive, power-of-two integer");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001188}
1189
1190TEST_F(ResolverValidationTest, ZeroStructMemberAlignAttribute) {
Tint teamf4626062022-05-06 08:50:33 +00001191 Structure("S", {
1192 Member("a", ty.f32(), {MemberAlign(Source{{12, 34}}, 0)}),
1193 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001194
Tint teamf4626062022-05-06 08:50:33 +00001195 EXPECT_FALSE(r()->Resolve());
1196 EXPECT_EQ(r()->error(), "12:34 error: align value must be a positive, power-of-two integer");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001197}
1198
1199TEST_F(ResolverValidationTest, ZeroStructMemberSizeAttribute) {
Tint teamf4626062022-05-06 08:50:33 +00001200 Structure("S", {
1201 Member("a", ty.f32(), {MemberSize(Source{{12, 34}}, 0)}),
1202 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001203
Tint teamf4626062022-05-06 08:50:33 +00001204 EXPECT_FALSE(r()->Resolve());
1205 EXPECT_EQ(r()->error(), "12:34 error: size must be at least as big as the type's size (4)");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001206}
1207
1208TEST_F(ResolverValidationTest, OffsetAndSizeAttribute) {
Tint teamf4626062022-05-06 08:50:33 +00001209 Structure("S", {
1210 Member(Source{{12, 34}}, "a", ty.f32(), {MemberOffset(0), MemberSize(4)}),
1211 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001212
Tint teamf4626062022-05-06 08:50:33 +00001213 EXPECT_FALSE(r()->Resolve());
1214 EXPECT_EQ(r()->error(),
1215 "12:34 error: offset attributes cannot be used with align or size "
1216 "attributes");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001217}
1218
1219TEST_F(ResolverValidationTest, OffsetAndAlignAttribute) {
Tint teamf4626062022-05-06 08:50:33 +00001220 Structure("S", {
1221 Member(Source{{12, 34}}, "a", ty.f32(), {MemberOffset(0), MemberAlign(4)}),
1222 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001223
Tint teamf4626062022-05-06 08:50:33 +00001224 EXPECT_FALSE(r()->Resolve());
1225 EXPECT_EQ(r()->error(),
1226 "12:34 error: offset attributes cannot be used with align or size "
1227 "attributes");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001228}
1229
1230TEST_F(ResolverValidationTest, OffsetAndAlignAndSizeAttribute) {
Tint teamf4626062022-05-06 08:50:33 +00001231 Structure("S", {
1232 Member(Source{{12, 34}}, "a", ty.f32(),
1233 {MemberOffset(0), MemberAlign(4), MemberSize(4)}),
1234 });
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001235
Tint teamf4626062022-05-06 08:50:33 +00001236 EXPECT_FALSE(r()->Resolve());
1237 EXPECT_EQ(r()->error(),
1238 "12:34 error: offset attributes cannot be used with align or size "
1239 "attributes");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001240}
1241
1242TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) {
Tint teamf4626062022-05-06 08:50:33 +00001243 auto* vf = Var("vf", ty.f32());
1244 auto* c =
1245 Construct(Source{{12, 34}}, ty.pointer<i32>(ast::StorageClass::kFunction), ExprList(vf));
1246 auto* ip = Let("ip", ty.pointer<i32>(ast::StorageClass::kFunction), c);
1247 WrapInFunction(Decl(vf), Decl(ip));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001248
Tint teamf4626062022-05-06 08:50:33 +00001249 EXPECT_FALSE(r()->Resolve());
1250 EXPECT_EQ(r()->error(), "12:34 error: type is not constructible");
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001251}
1252
1253} // namespace
Tint teamd2323c52022-04-11 20:49:10 +00001254} // namespace tint::resolver
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001255
1256TINT_INSTANTIATE_TYPEINFO(tint::resolver::FakeStmt);
1257TINT_INSTANTIATE_TYPEINFO(tint::resolver::FakeExpr);