validation: disallow atomic type constructors
The type of a type constructor must be constructible, which forbids atomics. Add checks for non-constructible types when validating arrays and structures, and then error on any type that isn't explicitly matched in the outer function. Replaces the separate check for pointers, which is no longer necessary. This also removes the validation for "an expression must not evaluate to an atomic type". The only test that we had for this is no longer valid (since the type constructor it used is now rejected). There are no other ways of hitting this particular error, since other validation rules will always kick in first. Change-Id: I2172b57ee4e8ee3066aaf0cedc4a26aaca642376 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/61800 Kokoro: Kokoro <noreply+kokoro@google.com> Auto-Submit: James Price <jrprice@google.com> Commit-Queue: Sarah Mashayekhi <sarahmashay@google.com> Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
This commit is contained in:
parent
8094553c8a
commit
cbbb420952
|
@ -327,14 +327,6 @@ TEST_F(ResolverAtomicValidationTest, Local) {
|
||||||
"12:34 error: function variable must have a constructible type");
|
"12:34 error: function variable must have a constructible type");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverAtomicValidationTest, NoAtomicExpr) {
|
|
||||||
WrapInFunction(Construct(Source{{12, 34}}, ty.atomic<u32>()));
|
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
|
||||||
EXPECT_EQ(r()->error(),
|
|
||||||
"12:34 error: an expression must not evaluate to an atomic type");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -2241,13 +2241,6 @@ bool Resolver::Expression(ast::Expression* expr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* ty = TypeOf(expr);
|
|
||||||
if (ty->Is<sem::Atomic>()) {
|
|
||||||
AddError("an expression must not evaluate to an atomic type",
|
|
||||||
expr->source());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2600,11 +2593,6 @@ bool Resolver::Constructor(ast::ConstructorExpression* expr) {
|
||||||
// Now that the argument types have been determined, make sure that they
|
// Now that the argument types have been determined, make sure that they
|
||||||
// obey the constructor type rules laid out in
|
// obey the constructor type rules laid out in
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl.html#type-constructor-expr.
|
// https://gpuweb.github.io/gpuweb/wgsl.html#type-constructor-expr.
|
||||||
if (type->Is<sem::Pointer>()) {
|
|
||||||
AddError("cannot cast to a pointer", expr->source());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
if (auto* vec_type = type->As<sem::Vector>()) {
|
if (auto* vec_type = type->As<sem::Vector>()) {
|
||||||
ok = ValidateVectorConstructor(type_ctor, vec_type, type_name);
|
ok = ValidateVectorConstructor(type_ctor, vec_type, type_name);
|
||||||
|
@ -2616,6 +2604,9 @@ bool Resolver::Constructor(ast::ConstructorExpression* expr) {
|
||||||
ok = ValidateArrayConstructor(type_ctor, arr_type);
|
ok = ValidateArrayConstructor(type_ctor, arr_type);
|
||||||
} else if (auto* struct_type = type->As<sem::Struct>()) {
|
} else if (auto* struct_type = type->As<sem::Struct>()) {
|
||||||
ok = ValidateStructureConstructor(type_ctor, struct_type);
|
ok = ValidateStructureConstructor(type_ctor, struct_type);
|
||||||
|
} else {
|
||||||
|
AddError("type is not constructible", type_ctor->source());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2641,6 +2632,11 @@ bool Resolver::Constructor(ast::ConstructorExpression* expr) {
|
||||||
bool Resolver::ValidateStructureConstructor(
|
bool Resolver::ValidateStructureConstructor(
|
||||||
const ast::TypeConstructorExpression* ctor,
|
const ast::TypeConstructorExpression* ctor,
|
||||||
const sem::Struct* struct_type) {
|
const sem::Struct* struct_type) {
|
||||||
|
if (!struct_type->IsConstructible()) {
|
||||||
|
AddError("struct constructor has non-constructible type", ctor->source());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctor->values().size() > 0) {
|
if (ctor->values().size() > 0) {
|
||||||
if (ctor->values().size() != struct_type->Members().size()) {
|
if (ctor->values().size() != struct_type->Members().size()) {
|
||||||
std::string fm = ctor->values().size() < struct_type->Members().size()
|
std::string fm = ctor->values().size() < struct_type->Members().size()
|
||||||
|
@ -2689,6 +2685,10 @@ bool Resolver::ValidateArrayConstructor(
|
||||||
if (array_type->IsRuntimeSized()) {
|
if (array_type->IsRuntimeSized()) {
|
||||||
AddError("cannot init a runtime-sized array", ctor->source());
|
AddError("cannot init a runtime-sized array", ctor->source());
|
||||||
return false;
|
return false;
|
||||||
|
} else if (!elem_type->IsConstructible()) {
|
||||||
|
AddError("array constructor has non-constructible element type",
|
||||||
|
ctor->type()->As<ast::Array>()->type()->source());
|
||||||
|
return false;
|
||||||
} else if (!values.empty() && (values.size() != array_type->Count())) {
|
} else if (!values.empty() && (values.size() != array_type->Count())) {
|
||||||
std::string fm = values.size() < array_type->Count() ? "few" : "many";
|
std::string fm = values.size() < array_type->Count() ? "few" : "many";
|
||||||
AddError("array constructor has too " + fm + " elements: expected " +
|
AddError("array constructor has too " + fm + " elements: expected " +
|
||||||
|
|
|
@ -2148,6 +2148,44 @@ TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct_Empty) {
|
||||||
}
|
}
|
||||||
} // namespace StructConstructor
|
} // namespace StructConstructor
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeConstructorValidationTest, NonConstructibleType_Atomic) {
|
||||||
|
WrapInFunction(
|
||||||
|
Call("ignore", Construct(Source{{12, 34}}, ty.atomic(ty.i32()))));
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), "12:34 error: type is not constructible");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeConstructorValidationTest,
|
||||||
|
NonConstructibleType_AtomicArray) {
|
||||||
|
WrapInFunction(Call(
|
||||||
|
"ignore", Construct(ty.array(ty.atomic(Source{{12, 34}}, ty.i32()), 4))));
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(
|
||||||
|
r()->error(),
|
||||||
|
"12:34 error: array constructor has non-constructible element type");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeConstructorValidationTest,
|
||||||
|
NonConstructibleType_AtomicStructMember) {
|
||||||
|
auto* str = Structure("S", {Member("a", ty.atomic(ty.i32()))});
|
||||||
|
WrapInFunction(Call("ignore", Construct(Source{{12, 34}}, ty.Of(str))));
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
"12:34 error: struct constructor has non-constructible type");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeConstructorValidationTest, NonConstructibleType_Sampler) {
|
||||||
|
WrapInFunction(Call(
|
||||||
|
"ignore",
|
||||||
|
Construct(Source{{12, 34}}, ty.sampler(ast::SamplerKind::kSampler))));
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), "12:34 error: type is not constructible");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -919,7 +919,7 @@ TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) {
|
||||||
WrapInFunction(Decl(vf), Decl(ip));
|
WrapInFunction(Decl(vf), Decl(ip));
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(), "12:34 error: cannot cast to a pointer");
|
EXPECT_EQ(r()->error(), "12:34 error: type is not constructible");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue