resolver: Reject non-storage runtime-sized arrays
There were several cases where we were not rejecting these which were leading to ICEs or bad codegen. Fixed: tint:1248 Change-Id: I7cdf3b74d92b81b1067ad908af423ea0b5442328 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/76161 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
13c79bef23
commit
db2f5fcf10
|
@ -2650,6 +2650,14 @@ bool Resolver::ApplyStorageClassUsageToType(ast::StorageClass sc,
|
|||
}
|
||||
|
||||
if (auto* arr = ty->As<sem::Array>()) {
|
||||
if (arr->IsRuntimeSized() && sc != ast::StorageClass::kStorage) {
|
||||
AddError(
|
||||
"runtime-sized arrays can only be used in the <storage> storage "
|
||||
"class",
|
||||
usage);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ApplyStorageClassUsageToType(
|
||||
sc, const_cast<sem::Type*>(arr->ElemType()), usage);
|
||||
}
|
||||
|
|
|
@ -571,19 +571,6 @@ bool Resolver::ValidateGlobalVariable(const sem::Variable* var) {
|
|||
decl->source);
|
||||
return false;
|
||||
}
|
||||
for (auto* member : str->Members()) {
|
||||
if (auto* arr = member->Type()->As<sem::Array>()) {
|
||||
if (arr->IsRuntimeSized()) {
|
||||
AddError(
|
||||
"structure containing a runtime sized array "
|
||||
"cannot be used as a uniform buffer",
|
||||
decl->source);
|
||||
AddNote("structure is declared here", str->Declaration()->source);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -45,6 +45,52 @@ TEST_F(ResolverStorageClassValidationTest,
|
|||
"the function storage class");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArray) {
|
||||
Global(Source{{12, 34}}, "v", ty.array(ty.i32()),
|
||||
ast::StorageClass::kPrivate);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
12:34 note: while instantiating variable v)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArrayInStruct) {
|
||||
auto* s = Structure("S", {Member("m", ty.array(ty.i32()))}, {StructBlock()});
|
||||
Global(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kPrivate);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
note: while analysing structure member S.m
|
||||
12:34 note: while instantiating variable v)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArray) {
|
||||
Global(Source{{12, 34}}, "v", ty.array(ty.i32()),
|
||||
ast::StorageClass::kWorkgroup);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
12:34 note: while instantiating variable v)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArrayInStruct) {
|
||||
auto* s = Structure("S", {Member("m", ty.array(ty.i32()))}, {StructBlock()});
|
||||
Global(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kWorkgroup);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
note: while analysing structure member S.m
|
||||
12:34 note: while instantiating variable v)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) {
|
||||
// var<storage> g : i32;
|
||||
Global(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kStorage,
|
||||
|
@ -170,9 +216,11 @@ TEST_F(ResolverStorageClassValidationTest, UniformBuffer_Struct_Runtime) {
|
|||
});
|
||||
|
||||
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");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
note: while analysing structure member S.m
|
||||
56:78 note: while instantiating variable svar)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) {
|
||||
|
|
|
@ -411,9 +411,10 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayInFunction_Fail) {
|
|||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: runtime arrays may only appear as the last member of "
|
||||
"a struct");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
12:34 note: while instantiating variable a)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, Struct_Member_VectorNoType) {
|
||||
|
@ -575,7 +576,8 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsGlobalVariable) {
|
|||
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: runtime arrays may only appear as the last member of a struct)");
|
||||
R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
56:78 note: while instantiating variable g)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
|
||||
|
@ -586,7 +588,8 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
|
|||
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: runtime arrays may only appear as the last member of a struct)");
|
||||
R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
56:78 note: while instantiating variable g)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
|
||||
|
@ -610,9 +613,30 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
|
|||
});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve()) << r()->error();
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: runtime arrays may only appear as the last member of "
|
||||
"a struct");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
12:34 note: while instantiating parameter a)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, PtrToRuntimeArrayAsParameter_Fail) {
|
||||
// fn func(a : ptr<workgroup, array<u32>>) {}
|
||||
|
||||
auto* param =
|
||||
Param(Source{{12, 34}}, "a",
|
||||
ty.pointer(ty.array<i32>(), ast::StorageClass::kWorkgroup));
|
||||
|
||||
Func("func", ast::VariableList{param}, ty.void_(),
|
||||
ast::StatementList{
|
||||
Return(),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
EXPECT_FALSE(r()->Resolve()) << r()->error();
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
12:34 note: while instantiating parameter a)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsNotLast_Fail) {
|
||||
|
|
|
@ -262,13 +262,17 @@ TEST_F(ResolverVarLetValidationTest, NonConstructibleType_Atomic) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverVarLetValidationTest, NonConstructibleType_RuntimeArray) {
|
||||
auto* s = Structure("S", {Member("m", ty.array(ty.i32()))}, {StructBlock()});
|
||||
auto* v = Var("v", ty.Of(s));
|
||||
auto* s = Structure("S", {Member(Source{{56, 78}}, "m", ty.array(ty.i32()))},
|
||||
{StructBlock()});
|
||||
auto* v = Var(Source{{12, 34}}, "v", ty.Of(s));
|
||||
WrapInFunction(v);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"error: function variable must have a constructible type");
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
|
||||
56:78 note: while analysing structure member S.m
|
||||
12:34 note: while instantiating variable v)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverVarLetValidationTest, NonConstructibleType_Struct_WithAtomic) {
|
||||
|
|
Loading…
Reference in New Issue