resolver: Validate storage buffers have the [[block]] decoration
Fixed: tint:94
Change-Id: I1d3e512c030ec16031b8c8fcfbde0cd1db5d1ea4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48380
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/resolver/storage_class_validation_test.cc b/src/resolver/storage_class_validation_test.cc
index 5f9324e..5dfdd18 100644
--- a/src/resolver/storage_class_validation_test.cc
+++ b/src/resolver/storage_class_validation_test.cc
@@ -15,6 +15,7 @@
#include "src/resolver/resolver.h"
#include "gmock/gmock.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/resolver/resolver_test_helper.h"
#include "src/sem/struct.h"
#include "src/type/access_control_type.h"
@@ -34,7 +35,7 @@
"12:34 error v-0022: global variables must have a storage class");
}
-TEST_F(ResolverStorageClassValidationTest, Bool) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) {
// var<storage> g : bool;
Global(Source{{56, 78}}, "g", ty.bool_(), ast::StorageClass::kStorage);
@@ -45,7 +46,7 @@
R"(56:78 error: variables declared in the <storage> storage class must be of an [[access]] qualified structure type)");
}
-TEST_F(ResolverStorageClassValidationTest, Pointer) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) {
// var<storage> g : ptr<i32, input>;
Global(Source{{56, 78}}, "g", ty.pointer<i32>(ast::StorageClass::kInput),
ast::StorageClass::kStorage);
@@ -57,7 +58,7 @@
R"(56:78 error: variables declared in the <storage> storage class must be of an [[access]] qualified structure type)");
}
-TEST_F(ResolverStorageClassValidationTest, Array) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferArray) {
// var<storage> g : [[access(read)]] array<S, 3>;
auto* s = Structure("S", {Member("a", ty.f32())});
auto* a = ty.array(s, 3);
@@ -71,7 +72,7 @@
R"(56:78 error: variables declared in the <storage> storage class must be of an [[access]] qualified structure type)");
}
-TEST_F(ResolverStorageClassValidationTest, BoolAlias) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferBoolAlias) {
// type a = bool;
// var<storage> g : [[access(read)]] a;
auto* a = ty.alias("a", ty.bool_());
@@ -84,7 +85,7 @@
R"(56:78 error: variables declared in the <storage> storage class must be of an [[access]] qualified structure type)");
}
-TEST_F(ResolverStorageClassValidationTest, NoAccessControl) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferNoAccessControl) {
// var<storage> g : S;
auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())});
Global(Source{{56, 78}}, "g", s, ast::StorageClass::kStorage);
@@ -96,20 +97,39 @@
R"(56:78 error: variables declared in the <storage> storage class must be of an [[access]] qualified structure type)");
}
-TEST_F(ResolverStorageClassValidationTest, NoError_Basic) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferNoBlockDecoration) {
+ // struct S { x : i32 };
// var<storage> g : [[access(read)]] S;
- auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())});
+ auto* s = Structure(Source{{12, 34}}, "S", {Member("x", ty.i32())});
+ auto* a = ty.access(ast::AccessControl::kReadOnly, s);
+ Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage);
+
+ ASSERT_FALSE(r()->Resolve());
+
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: structure used as a storage buffer must be declared with the [[block]] decoration
+56:78 note: structure used as storage buffer here)");
+}
+
+TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Basic) {
+ // [[block]] struct S { x : i32 };
+ // var<storage> g : [[access(read)]] S;
+ auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
+ {create<ast::StructBlockDecoration>()});
auto* a = ty.access(ast::AccessControl::kReadOnly, s);
Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage);
ASSERT_TRUE(r()->Resolve());
}
-TEST_F(ResolverStorageClassValidationTest, NoError_Aliases) {
+TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Aliases) {
+ // [[block]] struct S { x : i32 };
// type a1 = S;
// type a2 = [[access(read)]] a1;
// var<storage> g : a2;
- auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())});
+ auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
+ {create<ast::StructBlockDecoration>()});
auto* a1 = ty.alias("a1", s);
auto* ac = ty.access(ast::AccessControl::kReadOnly, a1);
auto* a2 = ty.alias("a2", ac);