[validation] add implementation and unit test for v-0031 v-0031: A struct containing a runtime array must be in the 'storage' storage class Change-Id: I3f7f8bd70cb24514815d7fc19858f64fd40860ac Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/33361 Commit-Queue: Sarah Mashayekhi <sarahmashay@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc index 69f89f7..d495009 100644 --- a/src/validator/validator_impl.cc +++ b/src/validator/validator_impl.cc
@@ -73,12 +73,21 @@ for (auto* member : st->impl()->members()) { if (member->type()->UnwrapAll()->IsArray()) { auto* r = member->type()->UnwrapAll()->AsArray(); - if (r->IsRuntimeArray() && member != st->impl()->members().back()) { - set_error(member->source(), - "v-0015: runtime arrays may only appear as the last " - "member of a struct: '" + - member->name() + "'"); - return false; + if (r->IsRuntimeArray()) { + if (member != st->impl()->members().back()) { + set_error(member->source(), + "v-0015: runtime arrays may only appear as the last " + "member of a struct: '" + + member->name() + "'"); + return false; + } + if (!st->IsBlockDecorated()) { + set_error(member->source(), + "v-0031: a struct containing a runtime-sized array " + "must be in the 'storage' storage class: '" + + st->name() + "'"); + return false; + } } } }
diff --git a/src/validator/validator_type_test.cc b/src/validator/validator_type_test.cc index 95b33eb..52c57c2 100644 --- a/src/validator/validator_type_test.cc +++ b/src/validator/validator_type_test.cc
@@ -15,6 +15,7 @@ #include "gtest/gtest.h" #include "src/ast/array_accessor_expression.h" #include "src/ast/struct.h" +#include "src/ast/struct_block_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" #include "src/ast/type/alias_type.h" @@ -35,6 +36,34 @@ class ValidatorTypeTest : public ValidatorTestHelper, public testing::Test {}; TEST_F(ValidatorTypeTest, RuntimeArrayIsLast_Pass) { + // [[Block]] + // struct Foo { + // vf: f32; + // rt: array<f32>; + // }; + + ast::type::F32Type f32; + ast::type::ArrayType arr(&f32); + ast::StructMemberList members; + { + ast::StructMemberDecorationList deco; + members.push_back(create<ast::StructMember>("vf", &f32, deco)); + } + { + ast::StructMemberDecorationList deco; + members.push_back(create<ast::StructMember>( + Source{Source::Location{12, 34}}, "rt", &arr, deco)); + } + ast::StructDecorationList decos; + decos.push_back(create<ast::StructBlockDecoration>(Source{})); + auto* st = create<ast::Struct>(decos, members); + ast::type::StructType struct_type("Foo", st); + + mod()->AddConstructedType(&struct_type); + EXPECT_TRUE(v()->ValidateConstructedTypes(mod()->constructed_types())); +} + +TEST_F(ValidatorTypeTest, RuntimeArrayIsLastNoBlock_Fail) { // struct Foo { // vf: f32; // rt: array<f32>; @@ -57,10 +86,14 @@ ast::type::StructType struct_type("Foo", st); mod()->AddConstructedType(&struct_type); - EXPECT_TRUE(v()->ValidateConstructedTypes(mod()->constructed_types())); + EXPECT_FALSE(v()->ValidateConstructedTypes(mod()->constructed_types())); + EXPECT_EQ(v()->error(), + "12:34: v-0031: a struct containing a runtime-sized array must be " + "in the 'storage' storage class: 'Foo'"); } TEST_F(ValidatorTypeTest, RuntimeArrayIsNotLast_Fail) { + // [[Block]] // struct Foo { // rt: array<f32>; // vf: f32; @@ -79,6 +112,7 @@ members.push_back(create<ast::StructMember>("vf", &f32, deco)); } ast::StructDecorationList decos; + decos.push_back(create<ast::StructBlockDecoration>(Source{})); auto* st = create<ast::Struct>(decos, members); ast::type::StructType struct_type("Foo", st); @@ -90,6 +124,7 @@ } TEST_F(ValidatorTypeTest, AliasRuntimeArrayIsNotLast_Fail) { + // [[Block]] // type RTArr = array<u32>; // struct s { // b: RTArr; @@ -112,6 +147,7 @@ } ast::StructDecorationList decos; + decos.push_back(create<ast::StructBlockDecoration>(Source{})); auto* st = create<ast::Struct>(decos, members); ast::type::StructType struct_type("s", st); mod()->AddConstructedType(&struct_type); @@ -122,6 +158,7 @@ } TEST_F(ValidatorTypeTest, AliasRuntimeArrayIsLast_Pass) { + // [[Block]] // type RTArr = array<u32>; // struct s { // a: u32; @@ -143,6 +180,7 @@ Source{Source::Location{12, 34}}, "b", &alias, deco)); } ast::StructDecorationList decos; + decos.push_back(create<ast::StructBlockDecoration>(Source{})); auto* st = create<ast::Struct>(decos, members); ast::type::StructType struct_type("s", st); mod()->AddConstructedType(&struct_type);