mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-04 12:16:10 +00:00
tint/resolver: Handle diagnostic attributes on functions
Push a new diagnostic filter scope at the start of resolving a function and process function attributes immediately. Bug: tint:1809 Change-Id: I8a7f4a29e4b7556d0721ed28c49d795c166fea00 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/117568 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
e8ea579bce
commit
02855b5060
@ -71,5 +71,115 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaDirective) {
|
|||||||
EXPECT_TRUE(r()->error().empty());
|
EXPECT_TRUE(r()->error().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaAttribute) {
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kError, Expr("chromium_unreachable_code"));
|
||||||
|
|
||||||
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
|
||||||
|
EXPECT_FALSE(r()->Resolve());
|
||||||
|
EXPECT_EQ(r()->error(), R"(error: code is unreachable)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaAttribute) {
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kWarning, Expr("chromium_unreachable_code"));
|
||||||
|
|
||||||
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), R"(warning: code is unreachable)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaAttribute) {
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kInfo, Expr("chromium_unreachable_code"));
|
||||||
|
|
||||||
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), R"(note: code is unreachable)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaAttribute) {
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kOff, Expr("chromium_unreachable_code"));
|
||||||
|
|
||||||
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_TRUE(r()->error().empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective_OverriddenViaAttribute) {
|
||||||
|
// diagnostic(error, chromium_unreachable_code);
|
||||||
|
//
|
||||||
|
// @diagnostic(off, chromium_unreachable_code) fn foo() {
|
||||||
|
// return;
|
||||||
|
// return; // Should produce a warning
|
||||||
|
// }
|
||||||
|
DiagnosticDirective(ast::DiagnosticSeverity::kError, Expr("chromium_unreachable_code"));
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kWarning, Expr("chromium_unreachable_code"));
|
||||||
|
|
||||||
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), R"(warning: code is unreachable)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||||
|
// @diagnostic(off, chromium_unreachable_code) fn foo() {
|
||||||
|
// return;
|
||||||
|
// return; // Should not produce a diagnostic
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn zoo() {
|
||||||
|
// return;
|
||||||
|
// return; // Should produce a warning (default severity)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @diagnostic(info, chromium_unreachable_code) fn bar() {
|
||||||
|
// return;
|
||||||
|
// return; // Should produce an info
|
||||||
|
// }
|
||||||
|
{
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kOff, Expr("chromium_unreachable_code"));
|
||||||
|
Func("foo", {}, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Return(),
|
||||||
|
Return(Source{{12, 34}}),
|
||||||
|
},
|
||||||
|
utils::Vector{attr});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Func("bar", {}, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Return(),
|
||||||
|
Return(Source{{45, 67}}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(ast::DiagnosticSeverity::kInfo, Expr("chromium_unreachable_code"));
|
||||||
|
Func("zoo", {}, ty.void_(),
|
||||||
|
utils::Vector{
|
||||||
|
Return(),
|
||||||
|
Return(Source{{89, 10}}),
|
||||||
|
},
|
||||||
|
utils::Vector{attr});
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), R"(45:67 warning: code is unreachable
|
||||||
|
89:10 note: code is unreachable)");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::resolver
|
} // namespace tint::resolver
|
||||||
|
@ -966,6 +966,21 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||||||
utils::Hashmap<Symbol, Source, 8> parameter_names;
|
utils::Hashmap<Symbol, Source, 8> parameter_names;
|
||||||
utils::Vector<sem::Parameter*, 8> parameters;
|
utils::Vector<sem::Parameter*, 8> parameters;
|
||||||
|
|
||||||
|
validator_.DiagnosticFilters().Push();
|
||||||
|
TINT_DEFER(validator_.DiagnosticFilters().Pop());
|
||||||
|
for (auto* attr : decl->attributes) {
|
||||||
|
Mark(attr);
|
||||||
|
if (auto* dc = attr->As<ast::DiagnosticAttribute>()) {
|
||||||
|
Mark(dc->control);
|
||||||
|
if (!DiagnosticControl(dc->control)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!validator_.NoDuplicateAttributes(decl->attributes)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve all the parameters
|
// Resolve all the parameters
|
||||||
for (auto* param : decl->params) {
|
for (auto* param : decl->params) {
|
||||||
Mark(param);
|
Mark(param);
|
||||||
@ -1032,9 +1047,6 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||||||
return_location = value.Get();
|
return_location = value.Get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!validator_.NoDuplicateAttributes(decl->attributes)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* str = return_type->As<sem::Struct>()) {
|
if (auto* str = return_type->As<sem::Struct>()) {
|
||||||
if (!ApplyAddressSpaceUsageToType(type::AddressSpace::kNone, str, decl->source)) {
|
if (!ApplyAddressSpaceUsageToType(type::AddressSpace::kNone, str, decl->source)) {
|
||||||
@ -1096,10 +1108,6 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* attr : decl->attributes) {
|
|
||||||
Mark(attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!validator_.NoDuplicateAttributes(decl->return_type_attributes)) {
|
if (!validator_.NoDuplicateAttributes(decl->return_type_attributes)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1004,7 +1004,8 @@ bool Validator::Function(const sem::Function* func, ast::PipelineStage stage) co
|
|||||||
attr->source);
|
attr->source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!attr->IsAnyOf<ast::StageAttribute, ast::InternalAttribute>()) {
|
} else if (!attr->IsAnyOf<ast::DiagnosticAttribute, ast::StageAttribute,
|
||||||
|
ast::InternalAttribute>()) {
|
||||||
AddError("attribute is not valid for functions", attr->source);
|
AddError("attribute is not valid for functions", attr->source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user