resolver: Replace ICEs with proper errors
If you attempted to: * Use a function as a type * Use a variable as a type * Use a variable as a call target You would get an ICE. Replace these with proper error diagnostics. Change-Id: Ibbe4cd1b59b1aadd451aa0445ad137859aa071eb Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/79765 Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
88d1a433aa
commit
597fc4cdbe
|
@ -252,6 +252,19 @@ TEST_F(ResolverCallValidationTest, LetPointerPrivate) {
|
||||||
"identifier expression or a function parameter");
|
"identifier expression or a function parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverCallValidationTest, CallVariable) {
|
||||||
|
// var v : i32;
|
||||||
|
// fn f() {
|
||||||
|
// v();
|
||||||
|
// }
|
||||||
|
Global("v", ty.i32(), ast::StorageClass::kPrivate);
|
||||||
|
Func("f", {}, ty.void_(), {CallStmt(Call(Source{{12, 34}}, "v"))});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), R"(error: cannot call variable 'v'
|
||||||
|
note: 'v' declared here)");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace resolver
|
} // namespace resolver
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -266,12 +266,26 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
|
||||||
if (ty->As<ast::ExternalTexture>()) {
|
if (ty->As<ast::ExternalTexture>()) {
|
||||||
return builder_->create<sem::ExternalTexture>();
|
return builder_->create<sem::ExternalTexture>();
|
||||||
}
|
}
|
||||||
if (auto* type = ResolvedSymbol<sem::Type>(ty)) {
|
return Switch(
|
||||||
return type;
|
ResolvedSymbol(ty), //
|
||||||
}
|
[&](sem::Type* type) { return type; },
|
||||||
|
[&](sem::Variable* var) {
|
||||||
|
auto name = builder_->Symbols().NameFor(var->Declaration()->symbol);
|
||||||
|
AddError("cannot use variable '" + name + "' as type", ty->source);
|
||||||
|
AddNote("'" + name + "' declared here", var->Declaration()->source);
|
||||||
|
return nullptr;
|
||||||
|
},
|
||||||
|
[&](sem::Function* func) {
|
||||||
|
auto name = builder_->Symbols().NameFor(func->Declaration()->symbol);
|
||||||
|
AddError("cannot use function '" + name + "' as type", ty->source);
|
||||||
|
AddNote("'" + name + "' declared here", func->Declaration()->source);
|
||||||
|
return nullptr;
|
||||||
|
},
|
||||||
|
[&](Default) {
|
||||||
TINT_UNREACHABLE(Resolver, diagnostics_)
|
TINT_UNREACHABLE(Resolver, diagnostics_)
|
||||||
<< "Unhandled ast::Type: " << ty->TypeInfo().name;
|
<< "Unhandled ast::Type: " << ty->TypeInfo().name;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
});
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
|
@ -1347,18 +1361,24 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
||||||
Mark(ident);
|
Mark(ident);
|
||||||
|
|
||||||
auto* resolved = ResolvedSymbol(ident);
|
auto* resolved = ResolvedSymbol(ident);
|
||||||
if (auto* ty = As<sem::Type>(resolved)) {
|
return Switch(
|
||||||
return type_ctor_or_conv(ty);
|
resolved, //
|
||||||
}
|
[&](sem::Type* type) { return type_ctor_or_conv(type); },
|
||||||
|
[&](sem::Function* func) {
|
||||||
if (auto* fn = As<sem::Function>(resolved)) {
|
return FunctionCall(expr, func, std::move(args), arg_behaviors);
|
||||||
return FunctionCall(expr, fn, std::move(args), arg_behaviors);
|
},
|
||||||
}
|
[&](sem::Variable* var) {
|
||||||
|
auto name = builder_->Symbols().NameFor(var->Declaration()->symbol);
|
||||||
|
AddError("cannot call variable '" + name + "'", ident->source);
|
||||||
|
AddNote("'" + name + "' declared here", var->Declaration()->source);
|
||||||
|
return nullptr;
|
||||||
|
},
|
||||||
|
[&](Default) -> sem::Call* {
|
||||||
auto name = builder_->Symbols().NameFor(ident->symbol);
|
auto name = builder_->Symbols().NameFor(ident->symbol);
|
||||||
auto builtin_type = sem::ParseBuiltinType(name);
|
auto builtin_type = sem::ParseBuiltinType(name);
|
||||||
if (builtin_type != sem::BuiltinType::kNone) {
|
if (builtin_type != sem::BuiltinType::kNone) {
|
||||||
return BuiltinCall(expr, builtin_type, std::move(args), std::move(arg_tys));
|
return BuiltinCall(expr, builtin_type, std::move(args),
|
||||||
|
std::move(arg_tys));
|
||||||
}
|
}
|
||||||
|
|
||||||
TINT_ICE(Resolver, diagnostics_)
|
TINT_ICE(Resolver, diagnostics_)
|
||||||
|
@ -1367,6 +1387,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "name: " << builder_->Symbols().NameFor(ident->symbol);
|
<< "name: " << builder_->Symbols().NameFor(ident->symbol);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
||||||
|
|
|
@ -695,6 +695,30 @@ TEST_F(ResolverTypeValidationTest, ArrayOfNonStorableType) {
|
||||||
"an array");
|
"an array");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeValidationTest, VariableAsType) {
|
||||||
|
// var<private> a : i32;
|
||||||
|
// var<private> b : a;
|
||||||
|
Global("a", ty.i32(), ast::StorageClass::kPrivate);
|
||||||
|
Global("b", ty.type_name("a"), ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
R"(error: cannot use variable 'a' as type
|
||||||
|
note: 'a' declared here)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverTypeValidationTest, FunctionAsType) {
|
||||||
|
// fn f() {}
|
||||||
|
// var<private> v : f;
|
||||||
|
Func("f", {}, ty.void_(), {});
|
||||||
|
Global("v", ty.type_name("f"), ast::StorageClass::kPrivate);
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
R"(error: cannot use function 'f' as type
|
||||||
|
note: 'f' declared here)");
|
||||||
|
}
|
||||||
|
|
||||||
namespace GetCanonicalTests {
|
namespace GetCanonicalTests {
|
||||||
struct Params {
|
struct Params {
|
||||||
builder::ast_type_func_ptr create_ast_type;
|
builder::ast_type_func_ptr create_ast_type;
|
||||||
|
|
Loading…
Reference in New Issue