From de767b18421cab3ebff74b2311df24bbf62d0742 Mon Sep 17 00:00:00 2001 From: Sarah Date: Mon, 13 Sep 2021 19:30:19 +0000 Subject: [PATCH] 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 Kokoro: Kokoro Commit-Queue: Sarah Mashayekhi --- src/resolver/array_accessor_test.cc | 53 ++++++++++++++++++++++++++ src/resolver/resolver.cc | 10 ++--- src/resolver/validation_test.cc | 58 +++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 5 deletions(-) diff --git a/src/resolver/array_accessor_test.cc b/src/resolver/array_accessor_test.cc index 21883cd96b..a565d0cda5 100644 --- a/src/resolver/array_accessor_test.cc +++ b/src/resolver/array_accessor_test.cc @@ -257,6 +257,59 @@ TEST_F(ResolverArrayAccessorTest, Array_Literal_I32) { EXPECT_TRUE(r()->Resolve()) << r()->error(); } +TEST_F(ResolverArrayAccessorTest, EXpr_Deref_FuncGoodParent) { + // fn func(p: ptr>) -> f32 { + // let idx: u32 = u32(); + // let x: f32 = (*p)[idx]; + // return x; + // } + auto* p = + Param("p", ty.pointer(ty.vec4(), 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>) -> f32 { + // let idx: u32 = u32(); + // let x: f32 = *p[idx]; + // return x; + // } + auto* p = + Param("p", ty.pointer(ty.vec4(), 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>'"); +} + +TEST_F(ResolverArrayAccessorTest, Exr_Deref_BadParent) { + // var param: vec4 + // let x: f32 = *(¶m)[0]; + auto* param = Var("param", ty.vec4()); + 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, read_write>'"); +} + } // namespace } // namespace resolver } // namespace tint diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index 4abe0711d2..1b26b607f2 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -2348,8 +2348,7 @@ bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) { } else if (auto* mat = parent_type->As()) { ret = builder_->create(mat->type(), mat->rows()); } else { - AddError("invalid parent type (" + parent_type->type_name() + - ") in array accessor", + AddError("cannot index type '" + TypeNameOf(expr->array()) + "'", expr->source()); return false; } @@ -3126,9 +3125,10 @@ bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) { expr, builder_->create(expr, ret, current_statement_, std::move(swizzle))); } else { - AddError("invalid use of member accessor on a non-vector/non-struct " + - TypeNameOf(expr->structure()), - expr->source()); + AddError( + "invalid member accessor expression. Expected vector or struct, got '" + + TypeNameOf(expr->structure()) + "'", + expr->structure()->source()); return false; } diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc index aea23211fc..06cc2bb5d1 100644 --- a/src/resolver/validation_test.cc +++ b/src/resolver/validation_test.cc @@ -451,6 +451,64 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadIndex) { EXPECT_EQ(r()->error(), "3:3 error: invalid vector swizzle member"); } +TEST_F(ResolverValidationTest, Expr_MemberAccessor_BadParent) { + // var param: vec4 + // let ret: f32 = *(¶m).x; + auto* param = Var("param", ty.vec4()); + auto* x = create( + 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, read_write>'"); +} + +TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncGoodParent) { + // fn func(p: ptr>) -> f32 { + // let x: f32 = (*p).z; + // return x; + // } + auto* p = + Param("p", ty.pointer(ty.vec4(), ast::StorageClass::kFunction)); + auto* star_p = Deref(p); + auto* z = create( + 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>) -> f32 { + // let x: f32 = *p.z; + // return x; + // } + auto* p = + Param("p", ty.pointer(ty.vec4(), ast::StorageClass::kFunction)); + auto* z = create( + 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>'"); +} + TEST_F(ResolverValidationTest, Stmt_Loop_ContinueInLoopBodyBeforeDeclAndAfterDecl_UsageInContinuing) { // loop {