blob: bb5b7755ccd29c62b2142abbf03a8f76e15f81dd [file] [log] [blame]
// Copyright 2023 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/tint/lang/wgsl/sem/test_helper.h"
#include "src/tint/lang/wgsl/sem/module.h"
using namespace tint::number_suffixes; // NOLINT
namespace tint::sem {
namespace {
class DiagnosticSeverityTest : public TestHelper {
protected:
/// Create a program with two functions, setting the severity for "chromium.unreachable_code"
/// using an attribute. Test that we correctly track the severity of the filter for the
/// functions and the statements with them.
/// @param global_severity the global severity of the "chromium.unreachable_code" filter
void Run(builtin::DiagnosticSeverity global_severity) {
// @diagnostic(off, chromium.unreachable_code)
// fn foo() {
// @diagnostic(info, chromium.unreachable_code) {
// @diagnostic(error, chromium.unreachable_code)
// if (true) @diagnostic(warning, chromium.unreachable_code) {
// return;
// } else if (false) {
// return;
// } else @diagnostic(info, chromium.unreachable_code) {
// return;
// }
// return;
//
// @diagnostic(error, chromium.unreachable_code)
// switch (42) @diagnostic(off, chromium.unreachable_code) {
// case 0 @diagnostic(warning, chromium.unreachable_code) {
// return;
// }
// default {
// return;
// }
// }
//
// @diagnostic(error, chromium.unreachable_code)
// for (var i = 0; false; i++) @diagnostic(warning, chromium.unreachable_code) {
// return;
// }
//
// @diagnostic(warning, chromium.unreachable_code)
// loop @diagnostic(off, chromium.unreachable_code) {
// return;
// continuing @diagnostic(info, chromium.unreachable_code) {
// break if true;
// }
// }
//
// @diagnostic(error, chromium.unreachable_code)
// while (false) @diagnostic(warning, chromium.unreachable_code) {
// return;
// }
// }
// }
//
// fn bar() {
// return;
// }
auto rule = builtin::ChromiumDiagnosticRule::kUnreachableCode;
auto func_severity = builtin::DiagnosticSeverity::kOff;
auto block_severity = builtin::DiagnosticSeverity::kInfo;
auto if_severity = builtin::DiagnosticSeverity::kError;
auto if_body_severity = builtin::DiagnosticSeverity::kWarning;
auto else_body_severity = builtin::DiagnosticSeverity::kInfo;
auto switch_severity = builtin::DiagnosticSeverity::kError;
auto switch_body_severity = builtin::DiagnosticSeverity::kOff;
auto case_severity = builtin::DiagnosticSeverity::kWarning;
auto for_severity = builtin::DiagnosticSeverity::kError;
auto for_body_severity = builtin::DiagnosticSeverity::kWarning;
auto loop_severity = builtin::DiagnosticSeverity::kWarning;
auto loop_body_severity = builtin::DiagnosticSeverity::kOff;
auto continuing_severity = builtin::DiagnosticSeverity::kInfo;
auto while_severity = builtin::DiagnosticSeverity::kError;
auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
auto attr = [&](auto severity) {
return utils::Vector{DiagnosticAttribute(severity, "chromium", "unreachable_code")};
};
auto* return_foo_if = Return();
auto* return_foo_elseif = Return();
auto* return_foo_else = Return();
auto* return_foo_block = Return();
auto* return_foo_case = Return();
auto* return_foo_default = Return();
auto* return_foo_for = Return();
auto* return_foo_loop = Return();
auto* return_foo_while = Return();
auto* breakif_foo_continuing = BreakIf(Expr(true));
auto* else_stmt = Block(utils::Vector{return_foo_else}, attr(else_body_severity));
auto* elseif = If(Expr(false), Block(return_foo_elseif), Else(else_stmt));
auto* if_foo = If(Expr(true), Block(utils::Vector{return_foo_if}, attr(if_body_severity)),
Else(elseif), attr(if_severity));
auto* case_stmt =
Case(CaseSelector(0_a), Block(utils::Vector{return_foo_case}, attr(case_severity)));
auto* default_stmt = DefaultCase(Block(return_foo_default));
auto* swtch = Switch(42_a, utils::Vector{case_stmt, default_stmt}, attr(switch_severity),
attr(switch_body_severity));
auto* fl =
For(Decl(Var("i", ty.i32())), false, Increment("i"),
Block(utils::Vector{return_foo_for}, attr(for_body_severity)), attr(for_severity));
auto* l = Loop(Block(utils::Vector{return_foo_loop}, attr(loop_body_severity)),
Block(utils::Vector{breakif_foo_continuing}, attr(continuing_severity)),
attr(loop_severity));
auto* wl = While(false, Block(utils::Vector{return_foo_while}, attr(while_body_severity)),
attr(while_severity));
auto* block_1 =
Block(utils::Vector{if_foo, return_foo_block, swtch, fl, l, wl}, attr(block_severity));
auto* func_attr = DiagnosticAttribute(func_severity, "chromium", "unreachable_code");
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{block_1}, utils::Vector{func_attr});
auto* return_bar = Return();
auto* bar = Func("bar", {}, ty.void_(), utils::Vector{return_bar});
auto p = Build();
EXPECT_TRUE(p.IsValid()) << p.Diagnostics().str();
EXPECT_EQ(p.Sem().DiagnosticSeverity(foo, rule), func_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(block_1, rule), block_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(if_foo, rule), if_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(if_foo->condition, rule), if_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(if_foo->body, rule), if_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_if, rule), if_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(elseif, rule), if_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(elseif->condition, rule), if_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(elseif->body, rule), if_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_elseif, rule), if_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(else_stmt, rule), else_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_else, rule), else_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(swtch, rule), switch_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(swtch->condition, rule), switch_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(case_stmt, rule), switch_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(case_stmt->body, rule), case_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_case, rule), case_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(default_stmt, rule), switch_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_default, rule), switch_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(fl, rule), while_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->initializer, rule), for_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->condition, rule), for_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->continuing, rule), for_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(fl->body, rule), for_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_for, rule), for_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(l, rule), loop_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(l->body, rule), loop_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(l->continuing, rule), continuing_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(breakif_foo_continuing, rule), continuing_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_loop, rule), loop_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl, rule), while_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl->condition, rule), while_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(wl->body, rule), while_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_foo_while, rule), while_body_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(bar, rule), global_severity);
EXPECT_EQ(p.Sem().DiagnosticSeverity(return_bar, rule), global_severity);
}
};
TEST_F(DiagnosticSeverityTest, WithDirective) {
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
Run(builtin::DiagnosticSeverity::kError);
}
TEST_F(DiagnosticSeverityTest, WithoutDirective) {
Run(builtin::DiagnosticSeverity::kWarning);
}
} // namespace
} // namespace tint::sem