diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc index ea10cac219..bbcb505e7e 100644 --- a/src/resolver/resolver.cc +++ b/src/resolver/resolver.cc @@ -744,6 +744,21 @@ bool Resolver::ValidateGlobalVariable(const VariableInfo* info) { } return false; } + + for (auto* member : str->Members()) { + if (auto* arr = member->Type()->As()) { + if (arr->IsRuntimeSized()) { + diagnostics_.add_error( + "structure containing a runtime sized array " + "cannot be used as a uniform buffer", + info->declaration->source()); + diagnostics_.add_note("structure is declared here", + str->Declaration()->source()); + return false; + } + } + } + break; } default: diff --git a/src/resolver/storage_class_validation_test.cc b/src/resolver/storage_class_validation_test.cc index d1fdaa88a0..84e7463e7a 100644 --- a/src/resolver/storage_class_validation_test.cc +++ b/src/resolver/storage_class_validation_test.cc @@ -152,7 +152,24 @@ TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Aliases) { ASSERT_TRUE(r()->Resolve()); } -/// +TEST_F(ResolverStorageClassValidationTest, UniformBuffer_Struct_Runtime) { + // [[block]] struct S { m: array; }; + // [[set(0), binding(0)]] var svar : S; + + auto* s = Structure(Source{{12, 34}}, "S", {Member("m", ty.array())}, + {create()}); + + Global(Source{{56, 78}}, "svar", ty.Of(s), ast::StorageClass::kUniform, + ast::DecorationList{ + create(0), + create(0), + }); + + ASSERT_FALSE(r()->Resolve()); + EXPECT_EQ(r()->error(), + "56:78 error: structure containing a runtime sized array cannot be " + "used as a uniform buffer\n12:34 note: structure is declared here"); +} TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) { // var g : bool;