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:
parent
c306cda4db
commit
de767b1842
|
@ -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 = *(¶m)[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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 = *(¶m).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 {
|
||||||
|
|
Loading…
Reference in New Issue