validation: fix arrayAcceor/memberAccessor error msg and add unit-tests

Bug: tint:1172
Change-Id: Icbc920dbc6adc9a5c78b8ae7d700b527a4fa48f7
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/64100
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Sarah Mashayekhi <sarahmashay@google.com>
This commit is contained in:
Sarah 2021-09-13 19:30:19 +00:00 committed by Tint LUCI CQ
parent c306cda4db
commit de767b1842
3 changed files with 116 additions and 5 deletions

View File

@ -257,6 +257,59 @@ TEST_F(ResolverArrayAccessorTest, Array_Literal_I32) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverArrayAccessorTest, EXpr_Deref_FuncGoodParent) {
// fn func(p: ptr<function, vec4<f32>>) -> f32 {
// let idx: u32 = u32();
// let x: f32 = (*p)[idx];
// return x;
// }
auto* p =
Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
auto* idx = Const("idx", ty.u32(), Construct(ty.u32()));
auto* star_p = Deref(p);
auto* accessor_expr = IndexAccessor(Source{{12, 34}}, star_p, idx);
auto* x = Var("x", ty.f32(), accessor_expr);
Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverArrayAccessorTest, EXpr_Deref_FuncBadParent) {
// fn func(p: ptr<function, vec4<f32>>) -> f32 {
// let idx: u32 = u32();
// let x: f32 = *p[idx];
// return x;
// }
auto* p =
Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
auto* idx = Const("idx", ty.u32(), Construct(ty.u32()));
auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
auto* star_p = Deref(accessor_expr);
auto* x = Var("x", ty.f32(), star_p);
Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: cannot index type 'ptr<function, vec4<f32>>'");
}
TEST_F(ResolverArrayAccessorTest, Exr_Deref_BadParent) {
// var param: vec4<f32>
// let x: f32 = *(&param)[0];
auto* param = Var("param", ty.vec4<f32>());
auto* idx = Var("idx", ty.u32(), Construct(ty.u32()));
auto* addressOf_expr = AddressOf(param);
auto* accessor_expr = IndexAccessor(Source{{12, 34}}, addressOf_expr, idx);
auto* star_p = Deref(accessor_expr);
auto* x = Var("x", ty.f32(), star_p);
WrapInFunction(param, idx, x);
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
"12:34 error: cannot index type 'ptr<function, vec4<f32>, read_write>'");
}
} // namespace } // namespace
} // namespace resolver } // namespace resolver
} // namespace tint } // namespace tint

View File

@ -2348,8 +2348,7 @@ bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) {
} else if (auto* mat = parent_type->As<sem::Matrix>()) { } else if (auto* mat = parent_type->As<sem::Matrix>()) {
ret = builder_->create<sem::Vector>(mat->type(), mat->rows()); ret = builder_->create<sem::Vector>(mat->type(), mat->rows());
} else { } else {
AddError("invalid parent type (" + parent_type->type_name() + AddError("cannot index type '" + TypeNameOf(expr->array()) + "'",
") in array accessor",
expr->source()); expr->source());
return false; return false;
} }
@ -3126,9 +3125,10 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) {
expr, builder_->create<sem::Swizzle>(expr, ret, current_statement_, expr, builder_->create<sem::Swizzle>(expr, ret, current_statement_,
std::move(swizzle))); std::move(swizzle)));
} else { } else {
AddError("invalid use of member accessor on a non-vector/non-struct " + AddError(
TypeNameOf(expr->structure()), "invalid member accessor expression. Expected vector or struct, got '" +
expr->source()); TypeNameOf(expr->structure()) + "'",
expr->structure()->source());
return false; return false;
} }

View File

@ -451,6 +451,64 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadIndex) {
EXPECT_EQ(r()->error(), "3:3 error: invalid vector swizzle member"); EXPECT_EQ(r()->error(), "3:3 error: invalid vector swizzle member");
} }
TEST_F(ResolverValidationTest, Expr_MemberAccessor_BadParent) {
// var param: vec4<f32>
// let ret: f32 = *(&param).x;
auto* param = Var("param", ty.vec4<f32>());
auto* x = create<ast::IdentifierExpression>(
Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
Symbols().Register("x"));
auto* addressOf_expr = AddressOf(Source{{12, 34}}, param);
auto* accessor_expr = MemberAccessor(addressOf_expr, x);
auto* star_p = Deref(accessor_expr);
auto* ret = Var("r", ty.f32(), star_p);
WrapInFunction(Decl(param), Decl(ret));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: invalid member accessor expression. Expected vector "
"or struct, got 'ptr<function, vec4<f32>, read_write>'");
}
TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncGoodParent) {
// fn func(p: ptr<function, vec4<f32>>) -> f32 {
// let x: f32 = (*p).z;
// return x;
// }
auto* p =
Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
auto* star_p = Deref(p);
auto* z = create<ast::IdentifierExpression>(
Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
Symbols().Register("z"));
auto* accessor_expr = MemberAccessor(star_p, z);
auto* x = Var("x", ty.f32(), accessor_expr);
Func("func", {p}, ty.f32(), {Decl(x), Return(x)});
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncBadParent) {
// fn func(p: ptr<function, vec4<f32>>) -> f32 {
// let x: f32 = *p.z;
// return x;
// }
auto* p =
Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
auto* z = create<ast::IdentifierExpression>(
Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
Symbols().Register("z"));
auto* accessor_expr = MemberAccessor(p, z);
auto* star_p = Deref(accessor_expr);
auto* x = Var("x", ty.f32(), star_p);
Func("func", {p}, ty.f32(), {Decl(x), Return(x)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"error: invalid member accessor expression. Expected vector or "
"struct, got 'ptr<function, vec4<f32>>'");
}
TEST_F(ResolverValidationTest, TEST_F(ResolverValidationTest,
Stmt_Loop_ContinueInLoopBodyBeforeDeclAndAfterDecl_UsageInContinuing) { Stmt_Loop_ContinueInLoopBodyBeforeDeclAndAfterDecl_UsageInContinuing) {
// loop { // loop {