diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc index 7b9e25a986..acba597625 100644 --- a/src/tint/lang/core/ir/validator.cc +++ b/src/tint/lang/core/ir/validator.cc @@ -1757,7 +1757,12 @@ void Validator::CheckType(const core::type::Type* root, auto visit = [&](const core::type::Type* type) { return tint::Switch( type, - [&](const core::type::Reference*) { + [&](const core::type::Reference* ref) { + if (ref->StoreType()->Is()) { + diag() << "references to void are not permitted"; + return false; + } + // Reference types are guarded by the AllowRefTypes capability. if (!capabilities_.Contains(Capability::kAllowRefTypes) || ignore_caps.Contains(Capability::kAllowRefTypes)) { @@ -1770,7 +1775,12 @@ void Validator::CheckType(const core::type::Type* root, } return true; }, - [&](const core::type::Pointer*) { + [&](const core::type::Pointer* ptr) { + if (ptr->StoreType()->Is()) { + diag() << "pointers to void are not permitted"; + return false; + } + if (type != root) { // Nesting pointer types inside structures is guarded by a capability. if (!(root->Is() && diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc index 1381505392..bb7b742f8d 100644 --- a/src/tint/lang/core/ir/validator_test.cc +++ b/src/tint/lang/core/ir/validator_test.cc @@ -5203,6 +5203,27 @@ note: # Disassembly )"); } +TEST_F(IR_ValidatorTest, Var_VoidType) { + mod.root_block->Append(b.Var(ty.ptr(private_, ty.void_()))); + + auto res = ir::Validate(mod); + ASSERT_NE(res, Success); + EXPECT_EQ(res.Failure().reason.Str(), R"(:2:3 error: var: pointers to void are not permitted + %1:ptr = var + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:1:1 note: in block +$B1: { # root +^^^ + +note: # Disassembly +$B1: { # root + %1:ptr = var +} + +)"); +} + TEST_F(IR_ValidatorTest, Var_Function_NullResult) { auto* v = mod.CreateInstruction(nullptr); v->SetInitializer(b.Constant(0_i)); @@ -9897,6 +9918,20 @@ TEST_F(IR_ValidatorTest, PointerToPointer) { testing::HasSubstr("nested pointer types are not permitted")); } +TEST_F(IR_ValidatorTest, PointerToVoid) { + auto* type = ty.ptr(AddressSpace::kFunction, ty.void_()); + auto* fn = b.Function("my_func", ty.void_()); + fn->SetParams(Vector{b.FunctionParam(type)}); + b.Append(fn->Block(), [&] { // + b.Return(fn); + }); + + auto res = ir::Validate(mod); + ASSERT_NE(res, Success); + EXPECT_THAT(res.Failure().reason.Str(), + testing::HasSubstr("pointers to void are not permitted")); +} + TEST_F(IR_ValidatorTest, ReferenceToReference) { auto* type = ty.ref(ty.ref()); auto* fn = b.Function("my_func", ty.void_()); @@ -9914,6 +9949,23 @@ TEST_F(IR_ValidatorTest, ReferenceToReference) { testing::HasSubstr("nested reference types are not permitted")); } +TEST_F(IR_ValidatorTest, ReferenceToVoid) { + auto* type = ty.ref(AddressSpace::kFunction, ty.void_()); + auto* fn = b.Function("my_func", ty.void_()); + b.Append(fn->Block(), [&] { // + b.Var(type); + b.Return(fn); + }); + + Capabilities caps; + caps.Add(Capability::kAllowRefTypes); + + auto res = ir::Validate(mod, caps); + ASSERT_NE(res, Success); + EXPECT_THAT(res.Failure().reason.Str(), + testing::HasSubstr("references to void are not permitted")); +} + TEST_F(IR_ValidatorTest, PointerInStructure_WithoutCapability) { auto* str_ty = ty.Struct(mod.symbols.New("S"), {