tint: Add two-token form for diagnostics rule names.
Fixed: tint:1891 Change-Id: Ia3737c29b111d7b6e6b00fbd68da7f85a5a49bca Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/128301 Commit-Queue: Ben Clayton <bclayton@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Reviewed-by: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
6cb055b6aa
commit
7883a0cb8d
|
@ -472,6 +472,7 @@ libtint_source_set("libtint_ast_hdrs") {
|
||||||
"ast/diagnostic_attribute.h",
|
"ast/diagnostic_attribute.h",
|
||||||
"ast/diagnostic_control.h",
|
"ast/diagnostic_control.h",
|
||||||
"ast/diagnostic_directive.h",
|
"ast/diagnostic_directive.h",
|
||||||
|
"ast/diagnostic_rule_name.h",
|
||||||
"ast/disable_validation_attribute.h",
|
"ast/disable_validation_attribute.h",
|
||||||
"ast/discard_statement.h",
|
"ast/discard_statement.h",
|
||||||
"ast/enable.h",
|
"ast/enable.h",
|
||||||
|
@ -559,6 +560,7 @@ libtint_source_set("libtint_ast_src") {
|
||||||
"ast/diagnostic_attribute.cc",
|
"ast/diagnostic_attribute.cc",
|
||||||
"ast/diagnostic_control.cc",
|
"ast/diagnostic_control.cc",
|
||||||
"ast/diagnostic_directive.cc",
|
"ast/diagnostic_directive.cc",
|
||||||
|
"ast/diagnostic_rule_name.cc",
|
||||||
"ast/disable_validation_attribute.cc",
|
"ast/disable_validation_attribute.cc",
|
||||||
"ast/discard_statement.cc",
|
"ast/discard_statement.cc",
|
||||||
"ast/enable.cc",
|
"ast/enable.cc",
|
||||||
|
@ -1291,6 +1293,7 @@ if (tint_build_unittests) {
|
||||||
"ast/diagnostic_attribute_test.cc",
|
"ast/diagnostic_attribute_test.cc",
|
||||||
"ast/diagnostic_control_test.cc",
|
"ast/diagnostic_control_test.cc",
|
||||||
"ast/diagnostic_directive_test.cc",
|
"ast/diagnostic_directive_test.cc",
|
||||||
|
"ast/diagnostic_rule_name_test.cc",
|
||||||
"ast/discard_statement_test.cc",
|
"ast/discard_statement_test.cc",
|
||||||
"ast/enable_test.cc",
|
"ast/enable_test.cc",
|
||||||
"ast/float_literal_expression_test.cc",
|
"ast/float_literal_expression_test.cc",
|
||||||
|
|
|
@ -126,6 +126,8 @@ list(APPEND TINT_LIB_SRCS
|
||||||
ast/diagnostic_control.h
|
ast/diagnostic_control.h
|
||||||
ast/diagnostic_directive.cc
|
ast/diagnostic_directive.cc
|
||||||
ast/diagnostic_directive.h
|
ast/diagnostic_directive.h
|
||||||
|
ast/diagnostic_rule_name.cc
|
||||||
|
ast/diagnostic_rule_name.h
|
||||||
ast/disable_validation_attribute.cc
|
ast/disable_validation_attribute.cc
|
||||||
ast/disable_validation_attribute.h
|
ast/disable_validation_attribute.h
|
||||||
ast/discard_statement.cc
|
ast/discard_statement.cc
|
||||||
|
@ -845,6 +847,7 @@ if(TINT_BUILD_TESTS)
|
||||||
ast/diagnostic_attribute_test.cc
|
ast/diagnostic_attribute_test.cc
|
||||||
ast/diagnostic_control_test.cc
|
ast/diagnostic_control_test.cc
|
||||||
ast/diagnostic_directive_test.cc
|
ast/diagnostic_directive_test.cc
|
||||||
|
ast/diagnostic_rule_name_test.cc
|
||||||
ast/discard_statement_test.cc
|
ast/discard_statement_test.cc
|
||||||
ast/enable_test.cc
|
ast/enable_test.cc
|
||||||
ast/float_literal_expression_test.cc
|
ast/float_literal_expression_test.cc
|
||||||
|
|
|
@ -20,12 +20,20 @@ namespace {
|
||||||
using namespace tint::number_suffixes; // NOLINT
|
using namespace tint::number_suffixes; // NOLINT
|
||||||
using DiagnosticAttributeTest = TestHelper;
|
using DiagnosticAttributeTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(DiagnosticAttributeTest, Creation) {
|
TEST_F(DiagnosticAttributeTest, Name) {
|
||||||
auto* name = Ident("foo");
|
auto* d = DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "foo");
|
||||||
auto* d = DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, name);
|
|
||||||
EXPECT_EQ(d->Name(), "diagnostic");
|
EXPECT_EQ(d->Name(), "diagnostic");
|
||||||
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kWarning);
|
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kWarning);
|
||||||
EXPECT_EQ(d->control.rule_name, name);
|
EXPECT_EQ(d->control.rule_name->category, nullptr);
|
||||||
|
CheckIdentifier(d->control.rule_name->name, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DiagnosticAttributeTest, CategoryAndName) {
|
||||||
|
auto* d = DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "foo", "bar");
|
||||||
|
EXPECT_EQ(d->Name(), "diagnostic");
|
||||||
|
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kWarning);
|
||||||
|
CheckIdentifier(d->control.rule_name->category, "foo");
|
||||||
|
CheckIdentifier(d->control.rule_name->name, "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -24,13 +24,10 @@ namespace tint::ast {
|
||||||
|
|
||||||
DiagnosticControl::DiagnosticControl() = default;
|
DiagnosticControl::DiagnosticControl() = default;
|
||||||
|
|
||||||
DiagnosticControl::DiagnosticControl(builtin::DiagnosticSeverity sev, const Identifier* rule)
|
DiagnosticControl::DiagnosticControl(builtin::DiagnosticSeverity sev,
|
||||||
|
const DiagnosticRuleName* rule)
|
||||||
: severity(sev), rule_name(rule) {
|
: severity(sev), rule_name(rule) {
|
||||||
TINT_ASSERT(AST, rule != nullptr);
|
TINT_ASSERT(AST, rule != nullptr);
|
||||||
if (rule) {
|
|
||||||
// It is invalid for a diagnostic rule name to be templated
|
|
||||||
TINT_ASSERT(AST, !rule->Is<TemplatedIdentifier>());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DiagnosticControl::DiagnosticControl(DiagnosticControl&&) = default;
|
DiagnosticControl::DiagnosticControl(DiagnosticControl&&) = default;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
namespace tint::ast {
|
namespace tint::ast {
|
||||||
class Identifier;
|
class DiagnosticRuleName;
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
||||||
namespace tint::ast {
|
namespace tint::ast {
|
||||||
|
@ -37,16 +37,16 @@ struct DiagnosticControl {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param sev the diagnostic severity
|
/// @param sev the diagnostic severity
|
||||||
/// @param rule the diagnostic rule name
|
/// @param rule the diagnostic rule name
|
||||||
DiagnosticControl(builtin::DiagnosticSeverity sev, const Identifier* rule);
|
DiagnosticControl(builtin::DiagnosticSeverity sev, const DiagnosticRuleName* rule);
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
DiagnosticControl(DiagnosticControl&&);
|
DiagnosticControl(DiagnosticControl&&);
|
||||||
|
|
||||||
/// The diagnostic severity control.
|
/// The diagnostic severity control.
|
||||||
builtin::DiagnosticSeverity severity;
|
builtin::DiagnosticSeverity severity = builtin::DiagnosticSeverity::kUndefined;
|
||||||
|
|
||||||
/// The diagnostic rule name.
|
/// The diagnostic rule name.
|
||||||
const Identifier* rule_name;
|
const DiagnosticRuleName* rule_name = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -24,12 +24,11 @@ namespace {
|
||||||
|
|
||||||
using DiagnosticControlTest = TestHelper;
|
using DiagnosticControlTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(DiagnosticControlTest, Assert_RuleNotTemplated) {
|
TEST_F(DiagnosticControlTest, Assert_RuleNotNull) {
|
||||||
EXPECT_FATAL_FAILURE(
|
EXPECT_FATAL_FAILURE(
|
||||||
{
|
{
|
||||||
ProgramBuilder b;
|
ProgramBuilder b;
|
||||||
DiagnosticControl control(builtin::DiagnosticSeverity::kWarning,
|
DiagnosticControl control(builtin::DiagnosticSeverity::kWarning, nullptr);
|
||||||
b.Ident("name", "a", "b", "c"));
|
|
||||||
},
|
},
|
||||||
"internal compiler error");
|
"internal compiler error");
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,5 @@ const DiagnosticDirective* DiagnosticDirective::Clone(CloneContext* ctx) const {
|
||||||
DiagnosticControl dc(control.severity, rule);
|
DiagnosticControl dc(control.severity, rule);
|
||||||
return ctx->dst->create<DiagnosticDirective>(src, std::move(dc));
|
return ctx->dst->create<DiagnosticDirective>(src, std::move(dc));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace tint::ast
|
} // namespace tint::ast
|
||||||
|
|
|
@ -21,15 +21,28 @@ namespace {
|
||||||
|
|
||||||
using DiagnosticDirectiveTest = TestHelper;
|
using DiagnosticDirectiveTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(DiagnosticDirectiveTest, Creation) {
|
TEST_F(DiagnosticDirectiveTest, Name) {
|
||||||
auto* diag = DiagnosticDirective(Source{{{10, 5}, {10, 15}}},
|
auto* d = DiagnosticDirective(Source{{{10, 5}, {10, 15}}},
|
||||||
builtin::DiagnosticSeverity::kWarning, "foo");
|
builtin::DiagnosticSeverity::kWarning, "foo");
|
||||||
EXPECT_EQ(diag->source.range.begin.line, 10u);
|
EXPECT_EQ(d->source.range.begin.line, 10u);
|
||||||
EXPECT_EQ(diag->source.range.begin.column, 5u);
|
EXPECT_EQ(d->source.range.begin.column, 5u);
|
||||||
EXPECT_EQ(diag->source.range.end.line, 10u);
|
EXPECT_EQ(d->source.range.end.line, 10u);
|
||||||
EXPECT_EQ(diag->source.range.end.column, 15u);
|
EXPECT_EQ(d->source.range.end.column, 15u);
|
||||||
EXPECT_EQ(diag->control.severity, builtin::DiagnosticSeverity::kWarning);
|
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kWarning);
|
||||||
CheckIdentifier(diag->control.rule_name, "foo");
|
EXPECT_EQ(d->control.rule_name->category, nullptr);
|
||||||
|
CheckIdentifier(d->control.rule_name->name, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DiagnosticDirectiveTest, CategoryAndName) {
|
||||||
|
auto* d = DiagnosticDirective(Source{{{10, 5}, {10, 15}}},
|
||||||
|
builtin::DiagnosticSeverity::kWarning, "foo", "bar");
|
||||||
|
EXPECT_EQ(d->source.range.begin.line, 10u);
|
||||||
|
EXPECT_EQ(d->source.range.begin.column, 5u);
|
||||||
|
EXPECT_EQ(d->source.range.end.line, 10u);
|
||||||
|
EXPECT_EQ(d->source.range.end.column, 15u);
|
||||||
|
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kWarning);
|
||||||
|
CheckIdentifier(d->control.rule_name->category, "foo");
|
||||||
|
CheckIdentifier(d->control.rule_name->name, "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
// 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/ast/diagnostic_rule_name.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "src/tint/program_builder.h"
|
||||||
|
|
||||||
|
TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticRuleName);
|
||||||
|
|
||||||
|
namespace tint::ast {
|
||||||
|
|
||||||
|
DiagnosticRuleName::DiagnosticRuleName(ProgramID pid,
|
||||||
|
NodeID nid,
|
||||||
|
const Source& src,
|
||||||
|
const Identifier* n)
|
||||||
|
: Base(pid, nid, src), name(n) {
|
||||||
|
TINT_ASSERT(AST, name != nullptr);
|
||||||
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
|
||||||
|
if (name) {
|
||||||
|
// It is invalid for a diagnostic rule name to be templated
|
||||||
|
TINT_ASSERT(AST, !name->Is<TemplatedIdentifier>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DiagnosticRuleName::DiagnosticRuleName(ProgramID pid,
|
||||||
|
NodeID nid,
|
||||||
|
const Source& src,
|
||||||
|
const Identifier* c,
|
||||||
|
const Identifier* n)
|
||||||
|
: Base(pid, nid, src), category(c), name(n) {
|
||||||
|
TINT_ASSERT(AST, name != nullptr);
|
||||||
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
|
||||||
|
if (name) {
|
||||||
|
// It is invalid for a diagnostic rule name to be templated
|
||||||
|
TINT_ASSERT(AST, !name->Is<TemplatedIdentifier>());
|
||||||
|
}
|
||||||
|
if (category) {
|
||||||
|
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, category, program_id);
|
||||||
|
// It is invalid for a diagnostic rule category to be templated
|
||||||
|
TINT_ASSERT(AST, !category->Is<TemplatedIdentifier>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DiagnosticRuleName* DiagnosticRuleName::Clone(CloneContext* ctx) const {
|
||||||
|
auto src = ctx->Clone(source);
|
||||||
|
auto n = ctx->Clone(name);
|
||||||
|
if (auto c = ctx->Clone(category)) {
|
||||||
|
return ctx->dst->create<DiagnosticRuleName>(src, c, n);
|
||||||
|
}
|
||||||
|
return ctx->dst->create<DiagnosticRuleName>(src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DiagnosticRuleName::String() const {
|
||||||
|
if (category) {
|
||||||
|
return category->symbol.Name() + "." + name->symbol.Name();
|
||||||
|
} else {
|
||||||
|
return name->symbol.Name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tint::ast
|
|
@ -0,0 +1,68 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef SRC_TINT_AST_DIAGNOSTIC_RULE_NAME_H_
|
||||||
|
#define SRC_TINT_AST_DIAGNOSTIC_RULE_NAME_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "src/tint/ast/node.h"
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
namespace tint::ast {
|
||||||
|
class Identifier;
|
||||||
|
} // namespace tint::ast
|
||||||
|
|
||||||
|
namespace tint::ast {
|
||||||
|
|
||||||
|
/// A diagnostic rule name used for diagnostic directives and attributes.
|
||||||
|
class DiagnosticRuleName final : public utils::Castable<DiagnosticRuleName, Node> {
|
||||||
|
public:
|
||||||
|
/// Constructor
|
||||||
|
/// @param pid the identifier of the program that owns this node
|
||||||
|
/// @param nid the unique node identifier
|
||||||
|
/// @param src the source of this node
|
||||||
|
/// @param name the rule name
|
||||||
|
DiagnosticRuleName(ProgramID pid, NodeID nid, const Source& src, const Identifier* name);
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
/// @param pid the identifier of the program that owns this node
|
||||||
|
/// @param nid the unique node identifier
|
||||||
|
/// @param src the source of this node
|
||||||
|
/// @param category the rule category.
|
||||||
|
/// @param name the rule name
|
||||||
|
DiagnosticRuleName(ProgramID pid,
|
||||||
|
NodeID nid,
|
||||||
|
const Source& src,
|
||||||
|
const Identifier* category,
|
||||||
|
const Identifier* name);
|
||||||
|
|
||||||
|
/// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
|
||||||
|
/// @param ctx the clone context
|
||||||
|
/// @return the newly cloned node
|
||||||
|
const DiagnosticRuleName* Clone(CloneContext* ctx) const override;
|
||||||
|
|
||||||
|
/// @return the full name of this diagnostic rule, either as `name` or `category.name`.
|
||||||
|
std::string String() const;
|
||||||
|
|
||||||
|
/// The diagnostic rule category (category.name)
|
||||||
|
Identifier const* const category = nullptr;
|
||||||
|
|
||||||
|
/// The diagnostic rule name.
|
||||||
|
Identifier const* const name;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tint::ast
|
||||||
|
|
||||||
|
#endif // SRC_TINT_AST_DIAGNOSTIC_RULE_NAME_H_
|
|
@ -0,0 +1,50 @@
|
||||||
|
// 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 <string>
|
||||||
|
|
||||||
|
#include "gtest/gtest-spi.h"
|
||||||
|
#include "src/tint/ast/diagnostic_rule_name.h"
|
||||||
|
#include "src/tint/ast/test_helper.h"
|
||||||
|
|
||||||
|
namespace tint::ast {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using DiagnosticRuleNameTest = TestHelper;
|
||||||
|
|
||||||
|
TEST_F(DiagnosticRuleNameTest, String) {
|
||||||
|
EXPECT_EQ(DiagnosticRuleName("name")->String(), "name");
|
||||||
|
EXPECT_EQ(DiagnosticRuleName("category", "name")->String(), "category.name");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DiagnosticRuleNameTest, Assert_NameNotTemplated) {
|
||||||
|
EXPECT_FATAL_FAILURE(
|
||||||
|
{
|
||||||
|
ProgramBuilder b;
|
||||||
|
b.create<ast::DiagnosticRuleName>(b.Ident("name", "a", "b", "c"));
|
||||||
|
},
|
||||||
|
"internal compiler error");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DiagnosticRuleNameTest, Assert_CategoryNotTemplated) {
|
||||||
|
EXPECT_FATAL_FAILURE(
|
||||||
|
{
|
||||||
|
ProgramBuilder b;
|
||||||
|
b.create<ast::DiagnosticRuleName>(b.Ident("name"), b.Ident("category", "a", "b", "c"));
|
||||||
|
},
|
||||||
|
"internal compiler error");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace tint::ast
|
|
@ -25,7 +25,7 @@ TEST(ModuleCloneTest, Clone) {
|
||||||
// Shader that exercises the bulk of the AST nodes and types.
|
// Shader that exercises the bulk of the AST nodes and types.
|
||||||
// See also fuzzers/tint_ast_clone_fuzzer.cc for further coverage of cloning.
|
// See also fuzzers/tint_ast_clone_fuzzer.cc for further coverage of cloning.
|
||||||
Source::File file("test.wgsl", R"(enable f16;
|
Source::File file("test.wgsl", R"(enable f16;
|
||||||
diagnostic(off, chromium_unreachable_code);
|
diagnostic(off, chromium.unreachable_code);
|
||||||
|
|
||||||
struct S0 {
|
struct S0 {
|
||||||
@size(4)
|
@size(4)
|
||||||
|
@ -65,7 +65,7 @@ fn f0(p0 : bool) -> f32 {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@diagnostic(warning, chromium_unreachable_code)
|
@diagnostic(warning, chromium.unreachable_code)
|
||||||
fn f1(p0 : f32, p1 : i32) -> f32 {
|
fn f1(p0 : f32, p1 : i32) -> f32 {
|
||||||
var l0 : i32 = 3;
|
var l0 : i32 = 3;
|
||||||
var l1 : f32 = 8.0;
|
var l1 : f32 = 8.0;
|
||||||
|
|
|
@ -28,29 +28,45 @@
|
||||||
|
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
|
|
||||||
/// ParseDiagnosticRule parses a DiagnosticRule from a string.
|
/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
|
||||||
/// @param str the string to parse
|
/// @param str the string to parse
|
||||||
/// @returns the parsed enum, or DiagnosticRule::kUndefined if the string could not be parsed.
|
/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
|
||||||
DiagnosticRule ParseDiagnosticRule(std::string_view str) {
|
CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str) {
|
||||||
if (str == "chromium_unreachable_code") {
|
|
||||||
return DiagnosticRule::kChromiumUnreachableCode;
|
|
||||||
}
|
|
||||||
if (str == "derivative_uniformity") {
|
if (str == "derivative_uniformity") {
|
||||||
return DiagnosticRule::kDerivativeUniformity;
|
return CoreDiagnosticRule::kDerivativeUniformity;
|
||||||
}
|
}
|
||||||
return DiagnosticRule::kUndefined;
|
return CoreDiagnosticRule::kUndefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::StringStream& operator<<(utils::StringStream& out, DiagnosticRule value) {
|
utils::StringStream& operator<<(utils::StringStream& out, CoreDiagnosticRule value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case DiagnosticRule::kUndefined:
|
case CoreDiagnosticRule::kUndefined:
|
||||||
return out << "undefined";
|
return out << "undefined";
|
||||||
case DiagnosticRule::kChromiumUnreachableCode:
|
case CoreDiagnosticRule::kDerivativeUniformity:
|
||||||
return out << "chromium_unreachable_code";
|
|
||||||
case DiagnosticRule::kDerivativeUniformity:
|
|
||||||
return out << "derivative_uniformity";
|
return out << "derivative_uniformity";
|
||||||
}
|
}
|
||||||
return out << "<unknown>";
|
return out << "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string.
|
||||||
|
/// @param str the string to parse
|
||||||
|
/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be
|
||||||
|
/// parsed.
|
||||||
|
ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str) {
|
||||||
|
if (str == "unreachable_code") {
|
||||||
|
return ChromiumDiagnosticRule::kUnreachableCode;
|
||||||
|
}
|
||||||
|
return ChromiumDiagnosticRule::kUndefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::StringStream& operator<<(utils::StringStream& out, ChromiumDiagnosticRule value) {
|
||||||
|
switch (value) {
|
||||||
|
case ChromiumDiagnosticRule::kUndefined:
|
||||||
|
return out << "undefined";
|
||||||
|
case ChromiumDiagnosticRule::kUnreachableCode:
|
||||||
|
return out << "unreachable_code";
|
||||||
|
}
|
||||||
|
return out << "<unknown>";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
|
@ -18,8 +18,12 @@ See:
|
||||||
|
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
|
|
||||||
{{ Eval "ParseEnum" (Sem.Enum "diagnostic_rule")}}
|
{{ Eval "ParseEnum" (Sem.Enum "core_diagnostic_rule")}}
|
||||||
|
|
||||||
{{ Eval "EnumOStream" (Sem.Enum "diagnostic_rule")}}
|
{{ Eval "EnumOStream" (Sem.Enum "core_diagnostic_rule")}}
|
||||||
|
|
||||||
|
{{ Eval "ParseEnum" (Sem.Enum "chromium_diagnostic_rule")}}
|
||||||
|
|
||||||
|
{{ Eval "EnumOStream" (Sem.Enum "chromium_diagnostic_rule")}}
|
||||||
|
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
|
@ -24,33 +24,56 @@
|
||||||
#define SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
#define SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
#include "src/tint/utils/string_stream.h"
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
|
|
||||||
/// The diagnostic rule.
|
/// WGSL core diagnostic rules.
|
||||||
enum class DiagnosticRule {
|
enum class CoreDiagnosticRule {
|
||||||
kUndefined,
|
kUndefined,
|
||||||
kChromiumUnreachableCode,
|
|
||||||
kDerivativeUniformity,
|
kDerivativeUniformity,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @param out the stream to write to
|
/// @param out the stream to write to
|
||||||
/// @param value the DiagnosticRule
|
/// @param value the CoreDiagnosticRule
|
||||||
/// @returns `out` so calls can be chained
|
/// @returns `out` so calls can be chained
|
||||||
utils::StringStream& operator<<(utils::StringStream& out, DiagnosticRule value);
|
utils::StringStream& operator<<(utils::StringStream& out, CoreDiagnosticRule value);
|
||||||
|
|
||||||
/// ParseDiagnosticRule parses a DiagnosticRule from a string.
|
/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
|
||||||
/// @param str the string to parse
|
/// @param str the string to parse
|
||||||
/// @returns the parsed enum, or DiagnosticRule::kUndefined if the string could not be parsed.
|
/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
|
||||||
DiagnosticRule ParseDiagnosticRule(std::string_view str);
|
CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str);
|
||||||
|
|
||||||
constexpr const char* kDiagnosticRuleStrings[] = {
|
constexpr const char* kCoreDiagnosticRuleStrings[] = {
|
||||||
"chromium_unreachable_code",
|
|
||||||
"derivative_uniformity",
|
"derivative_uniformity",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Chromium-specific diagnostic rules.
|
||||||
|
enum class ChromiumDiagnosticRule {
|
||||||
|
kUndefined,
|
||||||
|
kUnreachableCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @param out the stream to write to
|
||||||
|
/// @param value the ChromiumDiagnosticRule
|
||||||
|
/// @returns `out` so calls can be chained
|
||||||
|
utils::StringStream& operator<<(utils::StringStream& out, ChromiumDiagnosticRule value);
|
||||||
|
|
||||||
|
/// ParseChromiumDiagnosticRule parses a ChromiumDiagnosticRule from a string.
|
||||||
|
/// @param str the string to parse
|
||||||
|
/// @returns the parsed enum, or ChromiumDiagnosticRule::kUndefined if the string could not be
|
||||||
|
/// parsed.
|
||||||
|
ChromiumDiagnosticRule ParseChromiumDiagnosticRule(std::string_view str);
|
||||||
|
|
||||||
|
constexpr const char* kChromiumDiagnosticRuleStrings[] = {
|
||||||
|
"unreachable_code",
|
||||||
|
};
|
||||||
|
|
||||||
|
/// All diagnostic rules understood by Tint.
|
||||||
|
using DiagnosticRule = std::variant<CoreDiagnosticRule, ChromiumDiagnosticRule>;
|
||||||
|
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
||||||
#endif // SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
#endif // SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
||||||
|
|
|
@ -14,13 +14,20 @@ See:
|
||||||
#define SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
#define SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
#include "src/tint/utils/string_stream.h"
|
#include "src/tint/utils/string_stream.h"
|
||||||
|
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
|
|
||||||
/// The diagnostic rule.
|
/// WGSL core diagnostic rules.
|
||||||
{{ Eval "DeclareEnum" (Sem.Enum "diagnostic_rule") }}
|
{{ Eval "DeclareEnum" (Sem.Enum "core_diagnostic_rule") }}
|
||||||
|
|
||||||
|
/// Chromium-specific diagnostic rules.
|
||||||
|
{{ Eval "DeclareEnum" (Sem.Enum "chromium_diagnostic_rule") }}
|
||||||
|
|
||||||
|
/// All diagnostic rules understood by Tint.
|
||||||
|
using DiagnosticRule = std::variant<CoreDiagnosticRule, ChromiumDiagnosticRule>;
|
||||||
|
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
||||||
|
|
|
@ -29,23 +29,36 @@
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void DiagnosticRuleParser(::benchmark::State& state) {
|
void CoreDiagnosticRuleParser(::benchmark::State& state) {
|
||||||
const char* kStrings[] = {
|
const char* kStrings[] = {
|
||||||
"chromium_unrachaccle_code", "clromium_unreachab3_oe", "chromium_unreachable_Vode",
|
"deriative_unccformity", "dlivative_3iformiy", "derivative_uniforVity",
|
||||||
"chromium_unreachable_code", "chro1ium_unreachable_code", "chromium_unreJchableqqcde",
|
"derivative_uniformity", "derivative_uniform1ty", "derivativeJunifqrmity",
|
||||||
"chromium77unreallhable_code", "dqqrvatiHHe_uniforppity", "deriatcv_nvformity",
|
"derivative_unifllrmit77",
|
||||||
"derivatbe_unGformity", "derivative_uniformity", "derivative_iinifvrmity",
|
|
||||||
"derivat8WWe_uniformity", "drivaxxive_uniformity",
|
|
||||||
};
|
};
|
||||||
for (auto _ : state) {
|
for (auto _ : state) {
|
||||||
for (auto* str : kStrings) {
|
for (auto* str : kStrings) {
|
||||||
auto result = ParseDiagnosticRule(str);
|
auto result = ParseCoreDiagnosticRule(str);
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK(DiagnosticRuleParser);
|
BENCHMARK(CoreDiagnosticRuleParser);
|
||||||
|
|
||||||
|
void ChromiumDiagnosticRuleParser(::benchmark::State& state) {
|
||||||
|
const char* kStrings[] = {
|
||||||
|
"pqnreachableHHcode", "unrechcbe_cov", "unreachGblecode", "unreachable_code",
|
||||||
|
"vnriiachable_code", "unreac8ablWW_code", "unreMchablxxcode",
|
||||||
|
};
|
||||||
|
for (auto _ : state) {
|
||||||
|
for (auto* str : kStrings) {
|
||||||
|
auto result = ParseChromiumDiagnosticRule(str);
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(ChromiumDiagnosticRuleParser);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
|
@ -19,7 +19,9 @@ See:
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
{{ Eval "BenchmarkParseEnum" (Sem.Enum "diagnostic_rule")}}
|
{{ Eval "BenchmarkParseEnum" (Sem.Enum "core_diagnostic_rule")}}
|
||||||
|
|
||||||
|
{{ Eval "BenchmarkParseEnum" (Sem.Enum "chromium_diagnostic_rule")}}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
|
@ -29,13 +29,13 @@
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
namespace diagnostic_rule_tests {
|
namespace core_diagnostic_rule_tests {
|
||||||
|
|
||||||
namespace parse_print_tests {
|
namespace parse_print_tests {
|
||||||
|
|
||||||
struct Case {
|
struct Case {
|
||||||
const char* string;
|
const char* string;
|
||||||
DiagnosticRule value;
|
CoreDiagnosticRule value;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, Case c) {
|
inline std::ostream& operator<<(std::ostream& out, Case c) {
|
||||||
|
@ -43,43 +43,95 @@ inline std::ostream& operator<<(std::ostream& out, Case c) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr Case kValidCases[] = {
|
static constexpr Case kValidCases[] = {
|
||||||
{"chromium_unreachable_code", DiagnosticRule::kChromiumUnreachableCode},
|
{"derivative_uniformity", CoreDiagnosticRule::kDerivativeUniformity},
|
||||||
{"derivative_uniformity", DiagnosticRule::kDerivativeUniformity},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Case kInvalidCases[] = {
|
static constexpr Case kInvalidCases[] = {
|
||||||
{"chromium_unrachaccle_code", DiagnosticRule::kUndefined},
|
{"deriative_unccformity", CoreDiagnosticRule::kUndefined},
|
||||||
{"clromium_unreachab3_oe", DiagnosticRule::kUndefined},
|
{"dlivative_3iformiy", CoreDiagnosticRule::kUndefined},
|
||||||
{"chromium_unreachable_Vode", DiagnosticRule::kUndefined},
|
{"derivative_uniforVity", CoreDiagnosticRule::kUndefined},
|
||||||
{"derivative_uniform1ty", DiagnosticRule::kUndefined},
|
|
||||||
{"derivativeJunifqrmity", DiagnosticRule::kUndefined},
|
|
||||||
{"derivative_unifllrmit77", DiagnosticRule::kUndefined},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using DiagnosticRuleParseTest = testing::TestWithParam<Case>;
|
using CoreDiagnosticRuleParseTest = testing::TestWithParam<Case>;
|
||||||
|
|
||||||
TEST_P(DiagnosticRuleParseTest, Parse) {
|
TEST_P(CoreDiagnosticRuleParseTest, Parse) {
|
||||||
const char* string = GetParam().string;
|
const char* string = GetParam().string;
|
||||||
DiagnosticRule expect = GetParam().value;
|
CoreDiagnosticRule expect = GetParam().value;
|
||||||
EXPECT_EQ(expect, ParseDiagnosticRule(string));
|
EXPECT_EQ(expect, ParseCoreDiagnosticRule(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(ValidCases, DiagnosticRuleParseTest, testing::ValuesIn(kValidCases));
|
INSTANTIATE_TEST_SUITE_P(ValidCases, CoreDiagnosticRuleParseTest, testing::ValuesIn(kValidCases));
|
||||||
INSTANTIATE_TEST_SUITE_P(InvalidCases, DiagnosticRuleParseTest, testing::ValuesIn(kInvalidCases));
|
INSTANTIATE_TEST_SUITE_P(InvalidCases,
|
||||||
|
CoreDiagnosticRuleParseTest,
|
||||||
|
testing::ValuesIn(kInvalidCases));
|
||||||
|
|
||||||
using DiagnosticRulePrintTest = testing::TestWithParam<Case>;
|
using CoreDiagnosticRulePrintTest = testing::TestWithParam<Case>;
|
||||||
|
|
||||||
TEST_P(DiagnosticRulePrintTest, Print) {
|
TEST_P(CoreDiagnosticRulePrintTest, Print) {
|
||||||
DiagnosticRule value = GetParam().value;
|
CoreDiagnosticRule value = GetParam().value;
|
||||||
const char* expect = GetParam().string;
|
const char* expect = GetParam().string;
|
||||||
EXPECT_EQ(expect, utils::ToString(value));
|
EXPECT_EQ(expect, utils::ToString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(ValidCases, DiagnosticRulePrintTest, testing::ValuesIn(kValidCases));
|
INSTANTIATE_TEST_SUITE_P(ValidCases, CoreDiagnosticRulePrintTest, testing::ValuesIn(kValidCases));
|
||||||
|
|
||||||
} // namespace parse_print_tests
|
} // namespace parse_print_tests
|
||||||
|
|
||||||
} // namespace diagnostic_rule_tests
|
} // namespace core_diagnostic_rule_tests
|
||||||
|
|
||||||
|
namespace chromium_diagnostic_rule_tests {
|
||||||
|
|
||||||
|
namespace parse_print_tests {
|
||||||
|
|
||||||
|
struct Case {
|
||||||
|
const char* string;
|
||||||
|
ChromiumDiagnosticRule value;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& out, Case c) {
|
||||||
|
return out << "'" << std::string(c.string) << "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr Case kValidCases[] = {
|
||||||
|
{"unreachable_code", ChromiumDiagnosticRule::kUnreachableCode},
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr Case kInvalidCases[] = {
|
||||||
|
{"unreacha1le_code", ChromiumDiagnosticRule::kUndefined},
|
||||||
|
{"unreachableJcqde", ChromiumDiagnosticRule::kUndefined},
|
||||||
|
{"unreachable77llode", ChromiumDiagnosticRule::kUndefined},
|
||||||
|
};
|
||||||
|
|
||||||
|
using ChromiumDiagnosticRuleParseTest = testing::TestWithParam<Case>;
|
||||||
|
|
||||||
|
TEST_P(ChromiumDiagnosticRuleParseTest, Parse) {
|
||||||
|
const char* string = GetParam().string;
|
||||||
|
ChromiumDiagnosticRule expect = GetParam().value;
|
||||||
|
EXPECT_EQ(expect, ParseChromiumDiagnosticRule(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(ValidCases,
|
||||||
|
ChromiumDiagnosticRuleParseTest,
|
||||||
|
testing::ValuesIn(kValidCases));
|
||||||
|
INSTANTIATE_TEST_SUITE_P(InvalidCases,
|
||||||
|
ChromiumDiagnosticRuleParseTest,
|
||||||
|
testing::ValuesIn(kInvalidCases));
|
||||||
|
|
||||||
|
using ChromiumDiagnosticRulePrintTest = testing::TestWithParam<Case>;
|
||||||
|
|
||||||
|
TEST_P(ChromiumDiagnosticRulePrintTest, Print) {
|
||||||
|
ChromiumDiagnosticRule value = GetParam().value;
|
||||||
|
const char* expect = GetParam().string;
|
||||||
|
EXPECT_EQ(expect, utils::ToString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(ValidCases,
|
||||||
|
ChromiumDiagnosticRulePrintTest,
|
||||||
|
testing::ValuesIn(kValidCases));
|
||||||
|
|
||||||
|
} // namespace parse_print_tests
|
||||||
|
|
||||||
|
} // namespace chromium_diagnostic_rule_tests
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
|
@ -19,11 +19,17 @@ See:
|
||||||
namespace tint::builtin {
|
namespace tint::builtin {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
namespace diagnostic_rule_tests {
|
namespace core_diagnostic_rule_tests {
|
||||||
|
|
||||||
{{ Eval "TestParsePrintEnum" (Sem.Enum "diagnostic_rule")}}
|
{{ Eval "TestParsePrintEnum" (Sem.Enum "core_diagnostic_rule")}}
|
||||||
|
|
||||||
} // namespace diagnostic_rule_tests
|
} // namespace core_diagnostic_rule_tests
|
||||||
|
|
||||||
|
namespace chromium_diagnostic_rule_tests {
|
||||||
|
|
||||||
|
{{ Eval "TestParsePrintEnum" (Sem.Enum "chromium_diagnostic_rule")}}
|
||||||
|
|
||||||
|
} // namespace chromium_diagnostic_rule_tests
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace tint::builtin
|
} // namespace tint::builtin
|
||||||
|
|
|
@ -41,11 +41,15 @@ enum builtin_value {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#filterable-triggering-rules
|
// https://gpuweb.github.io/gpuweb/wgsl/#filterable-triggering-rules
|
||||||
enum diagnostic_rule {
|
enum core_diagnostic_rule {
|
||||||
// Rules defined in the spec.
|
// Rules defined in the spec.
|
||||||
derivative_uniformity
|
derivative_uniformity
|
||||||
|
}
|
||||||
|
|
||||||
|
// chromium-specific diagnostics
|
||||||
|
enum chromium_diagnostic_rule {
|
||||||
// Chromium specific rules not defined in the spec.
|
// Chromium specific rules not defined in the spec.
|
||||||
chromium_unreachable_code
|
unreachable_code
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://gpuweb.github.io/gpuweb/wgsl/#syntax-severity_control_name
|
// https://gpuweb.github.io/gpuweb/wgsl/#syntax-severity_control_name
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "src/tint/ast/diagnostic_attribute.h"
|
#include "src/tint/ast/diagnostic_attribute.h"
|
||||||
#include "src/tint/ast/diagnostic_control.h"
|
#include "src/tint/ast/diagnostic_control.h"
|
||||||
#include "src/tint/ast/diagnostic_directive.h"
|
#include "src/tint/ast/diagnostic_directive.h"
|
||||||
|
#include "src/tint/ast/diagnostic_rule_name.h"
|
||||||
#include "src/tint/ast/disable_validation_attribute.h"
|
#include "src/tint/ast/disable_validation_attribute.h"
|
||||||
#include "src/tint/ast/discard_statement.h"
|
#include "src/tint/ast/discard_statement.h"
|
||||||
#include "src/tint/ast/enable.h"
|
#include "src/tint/ast/enable.h"
|
||||||
|
@ -3752,57 +3753,129 @@ class ProgramBuilder {
|
||||||
validation);
|
validation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an ast::DiagnosticAttribute
|
/// Passthrough overload
|
||||||
/// @param source the source information
|
/// @param name the diagnostic rule name
|
||||||
/// @param severity the diagnostic severity control
|
/// @returns @p name
|
||||||
/// @param rule_name the diagnostic rule name
|
const ast::DiagnosticRuleName* DiagnosticRuleName(const ast::DiagnosticRuleName* name) {
|
||||||
/// @returns the diagnostic attribute pointer
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an ast::DiagnosticRuleName
|
||||||
|
/// @param name the diagnostic rule name
|
||||||
|
/// @returns the diagnostic rule name
|
||||||
template <typename NAME>
|
template <typename NAME>
|
||||||
const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source,
|
const ast::DiagnosticRuleName* DiagnosticRuleName(NAME&& name) {
|
||||||
builtin::DiagnosticSeverity severity,
|
|
||||||
NAME&& rule_name) {
|
|
||||||
static_assert(
|
static_assert(
|
||||||
!utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
|
!utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
|
||||||
"it is invalid for a diagnostic rule name to be templated");
|
"it is invalid for a diagnostic rule name to be templated");
|
||||||
|
auto* name_ident = Ident(std::forward<NAME>(name));
|
||||||
|
return create<ast::DiagnosticRuleName>(name_ident->source, name_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an ast::DiagnosticRuleName
|
||||||
|
/// @param category the diagnostic rule category
|
||||||
|
/// @param name the diagnostic rule name
|
||||||
|
/// @returns the diagnostic rule name
|
||||||
|
template <typename CATEGORY, typename NAME, typename = DisableIfSource<CATEGORY>>
|
||||||
|
const ast::DiagnosticRuleName* DiagnosticRuleName(CATEGORY&& category, NAME&& name) {
|
||||||
|
static_assert(
|
||||||
|
!utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
|
||||||
|
"it is invalid for a diagnostic rule name to be templated");
|
||||||
|
static_assert(
|
||||||
|
!utils::traits::IsType<utils::traits::PtrElTy<CATEGORY>, ast::TemplatedIdentifier>,
|
||||||
|
"it is invalid for a diagnostic rule category to be templated");
|
||||||
|
auto* category_ident = Ident(std::forward<CATEGORY>(category));
|
||||||
|
auto* name_ident = Ident(std::forward<NAME>(name));
|
||||||
|
Source source = category_ident->source;
|
||||||
|
source.range.end = name_ident->source.range.end;
|
||||||
|
return create<ast::DiagnosticRuleName>(source, category_ident, name_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an ast::DiagnosticRuleName
|
||||||
|
/// @param source the source information
|
||||||
|
/// @param name the diagnostic rule name
|
||||||
|
/// @returns the diagnostic rule name
|
||||||
|
template <typename NAME>
|
||||||
|
const ast::DiagnosticRuleName* DiagnosticRuleName(const Source& source, NAME&& name) {
|
||||||
|
static_assert(
|
||||||
|
!utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
|
||||||
|
"it is invalid for a diagnostic rule name to be templated");
|
||||||
|
auto* name_ident = Ident(std::forward<NAME>(name));
|
||||||
|
return create<ast::DiagnosticRuleName>(source, name_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an ast::DiagnosticRuleName
|
||||||
|
/// @param source the source information
|
||||||
|
/// @param category the diagnostic rule category
|
||||||
|
/// @param name the diagnostic rule name
|
||||||
|
/// @returns the diagnostic rule name
|
||||||
|
template <typename CATEGORY, typename NAME>
|
||||||
|
const ast::DiagnosticRuleName* DiagnosticRuleName(const Source& source,
|
||||||
|
CATEGORY&& category,
|
||||||
|
NAME&& name) {
|
||||||
|
static_assert(
|
||||||
|
!utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
|
||||||
|
"it is invalid for a diagnostic rule name to be templated");
|
||||||
|
static_assert(
|
||||||
|
!utils::traits::IsType<utils::traits::PtrElTy<CATEGORY>, ast::TemplatedIdentifier>,
|
||||||
|
"it is invalid for a diagnostic rule category to be templated");
|
||||||
|
auto* category_ident = Ident(std::forward<CATEGORY>(category));
|
||||||
|
auto* name_ident = Ident(std::forward<NAME>(name));
|
||||||
|
return create<ast::DiagnosticRuleName>(source, category_ident, name_ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an ast::DiagnosticAttribute
|
||||||
|
/// @param source the source information
|
||||||
|
/// @param severity the diagnostic severity control
|
||||||
|
/// @param rule_args the arguments used to construct the rule name
|
||||||
|
/// @returns the diagnostic attribute pointer
|
||||||
|
template <typename... RULE_ARGS>
|
||||||
|
const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source,
|
||||||
|
builtin::DiagnosticSeverity severity,
|
||||||
|
RULE_ARGS&&... rule_args) {
|
||||||
return create<ast::DiagnosticAttribute>(
|
return create<ast::DiagnosticAttribute>(
|
||||||
source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
source, ast::DiagnosticControl(
|
||||||
|
severity, DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an ast::DiagnosticAttribute
|
/// Creates an ast::DiagnosticAttribute
|
||||||
/// @param severity the diagnostic severity control
|
/// @param severity the diagnostic severity control
|
||||||
/// @param rule_name the diagnostic rule name
|
/// @param rule_args the arguments used to construct the rule name
|
||||||
/// @returns the diagnostic attribute pointer
|
/// @returns the diagnostic attribute pointer
|
||||||
template <typename NAME>
|
template <typename... RULE_ARGS>
|
||||||
const ast::DiagnosticAttribute* DiagnosticAttribute(builtin::DiagnosticSeverity severity,
|
const ast::DiagnosticAttribute* DiagnosticAttribute(builtin::DiagnosticSeverity severity,
|
||||||
NAME&& rule_name) {
|
RULE_ARGS&&... rule_args) {
|
||||||
return create<ast::DiagnosticAttribute>(
|
return create<ast::DiagnosticAttribute>(
|
||||||
source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
source_, ast::DiagnosticControl(
|
||||||
|
severity, DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a diagnostic directive to the module.
|
/// Add a diagnostic directive to the module.
|
||||||
/// @param source the source information
|
/// @param source the source information
|
||||||
/// @param severity the diagnostic severity control
|
/// @param severity the diagnostic severity control
|
||||||
/// @param rule_name the diagnostic rule name
|
/// @param rule_args the arguments used to construct the rule name
|
||||||
/// @returns the diagnostic directive pointer
|
/// @returns the diagnostic directive pointer
|
||||||
template <typename NAME>
|
template <typename... RULE_ARGS>
|
||||||
const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
|
const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
|
||||||
builtin::DiagnosticSeverity severity,
|
builtin::DiagnosticSeverity severity,
|
||||||
NAME&& rule_name) {
|
RULE_ARGS&&... rule_args) {
|
||||||
auto* directive = create<ast::DiagnosticDirective>(
|
auto* rule = DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...);
|
||||||
source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
auto* directive =
|
||||||
|
create<ast::DiagnosticDirective>(source, ast::DiagnosticControl(severity, rule));
|
||||||
AST().AddDiagnosticDirective(directive);
|
AST().AddDiagnosticDirective(directive);
|
||||||
return directive;
|
return directive;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a diagnostic directive to the module.
|
/// Add a diagnostic directive to the module.
|
||||||
/// @param severity the diagnostic severity control
|
/// @param severity the diagnostic severity control
|
||||||
/// @param rule_name the diagnostic rule name
|
/// @param rule_args the arguments used to construct the rule name
|
||||||
/// @returns the diagnostic directive pointer
|
/// @returns the diagnostic directive pointer
|
||||||
template <typename NAME>
|
template <typename... RULE_ARGS>
|
||||||
const ast::DiagnosticDirective* DiagnosticDirective(builtin::DiagnosticSeverity severity,
|
const ast::DiagnosticDirective* DiagnosticDirective(builtin::DiagnosticSeverity severity,
|
||||||
NAME&& rule_name) {
|
RULE_ARGS&&... rule_args) {
|
||||||
auto* directive = create<ast::DiagnosticDirective>(
|
auto* rule = DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...);
|
||||||
source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
auto* directive =
|
||||||
|
create<ast::DiagnosticDirective>(source_, ast::DiagnosticControl(severity, rule));
|
||||||
AST().AddDiagnosticDirective(directive);
|
AST().AddDiagnosticDirective(directive);
|
||||||
return directive;
|
return directive;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3092,7 +3092,7 @@ Expect<builtin::DiagnosticSeverity> ParserImpl::expect_severity_control_name() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// diagnostic_control
|
// diagnostic_control
|
||||||
// : PAREN_LEFT severity_control_name COMMA ident_pattern_token COMMA ? PAREN_RIGHT
|
// : PAREN_LEFT severity_control_name COMMA diagnostic_rule_name COMMA ? PAREN_RIGHT
|
||||||
Expect<ast::DiagnosticControl> ParserImpl::expect_diagnostic_control() {
|
Expect<ast::DiagnosticControl> ParserImpl::expect_diagnostic_control() {
|
||||||
return expect_paren_block("diagnostic control", [&]() -> Expect<ast::DiagnosticControl> {
|
return expect_paren_block("diagnostic control", [&]() -> Expect<ast::DiagnosticControl> {
|
||||||
auto severity_control = expect_severity_control_name();
|
auto severity_control = expect_severity_control_name();
|
||||||
|
@ -3104,7 +3104,7 @@ Expect<ast::DiagnosticControl> ParserImpl::expect_diagnostic_control() {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rule_name = expect_ident("diagnostic control");
|
auto rule_name = expect_diagnostic_rule_name();
|
||||||
if (rule_name.errored) {
|
if (rule_name.errored) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
|
@ -3114,6 +3114,31 @@ Expect<ast::DiagnosticControl> ParserImpl::expect_diagnostic_control() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// diagnostic_rule_name :
|
||||||
|
// | diagnostic_name_token
|
||||||
|
// | diagnostic_name_token '.' diagnostic_name_token
|
||||||
|
Expect<const ast::DiagnosticRuleName*> ParserImpl::expect_diagnostic_rule_name() {
|
||||||
|
if (peek_is(Token::Type::kPeriod, 1)) {
|
||||||
|
auto category = expect_ident("", "diagnostic rule category");
|
||||||
|
if (category.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
if (!expect("diagnostic rule", Token::Type::kPeriod)) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
auto name = expect_ident("", "diagnostic rule name");
|
||||||
|
if (name.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return builder_.DiagnosticRuleName(category.value, name.value);
|
||||||
|
}
|
||||||
|
auto name = expect_ident("", "diagnostic rule name");
|
||||||
|
if (name.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
return builder_.DiagnosticRuleName(name.value);
|
||||||
|
}
|
||||||
|
|
||||||
bool ParserImpl::match(Token::Type tok, Source* source /*= nullptr*/) {
|
bool ParserImpl::match(Token::Type tok, Source* source /*= nullptr*/) {
|
||||||
auto& t = peek();
|
auto& t = peek();
|
||||||
|
|
||||||
|
@ -3214,7 +3239,9 @@ Expect<uint32_t> ParserImpl::expect_nonzero_positive_sint(std::string_view use)
|
||||||
return {static_cast<uint32_t>(sint.value), sint.source};
|
return {static_cast<uint32_t>(sint.value), sint.source};
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect<const ast::Identifier*> ParserImpl::expect_ident(std::string_view use) {
|
Expect<const ast::Identifier*> ParserImpl::expect_ident(
|
||||||
|
std::string_view use,
|
||||||
|
std::string_view kind /* = "identifier" */) {
|
||||||
auto& t = peek();
|
auto& t = peek();
|
||||||
if (t.IsIdentifier()) {
|
if (t.IsIdentifier()) {
|
||||||
synchronized_ = true;
|
synchronized_ = true;
|
||||||
|
@ -3230,7 +3257,7 @@ Expect<const ast::Identifier*> ParserImpl::expect_ident(std::string_view use) {
|
||||||
return Failure::kErrored;
|
return Failure::kErrored;
|
||||||
}
|
}
|
||||||
synchronized_ = false;
|
synchronized_ = false;
|
||||||
return add_error(t.source(), "expected identifier", use);
|
return add_error(t.source(), "expected " + std::string(kind), use);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F, typename T>
|
template <typename F, typename T>
|
||||||
|
|
|
@ -636,14 +636,17 @@ class ParserImpl {
|
||||||
/// Parses a single attribute, reporting an error if the next token does not
|
/// Parses a single attribute, reporting an error if the next token does not
|
||||||
/// represent a attribute.
|
/// represent a attribute.
|
||||||
/// @see #attribute for the full list of attributes this method parses.
|
/// @see #attribute for the full list of attributes this method parses.
|
||||||
/// @return the parsed attribute, or nullptr on error.
|
/// @return the parsed attribute.
|
||||||
Expect<const ast::Attribute*> expect_attribute();
|
Expect<const ast::Attribute*> expect_attribute();
|
||||||
/// Parses a severity_control_name grammar element.
|
/// Parses a severity_control_name grammar element.
|
||||||
/// @return the parsed severity control name, or nullptr on error.
|
/// @return the parsed severity control name.
|
||||||
Expect<builtin::DiagnosticSeverity> expect_severity_control_name();
|
Expect<builtin::DiagnosticSeverity> expect_severity_control_name();
|
||||||
/// Parses a diagnostic_control grammar element.
|
/// Parses a diagnostic_control grammar element.
|
||||||
/// @return the parsed diagnostic control, or nullptr on error.
|
/// @return the parsed diagnostic control.
|
||||||
Expect<ast::DiagnosticControl> expect_diagnostic_control();
|
Expect<ast::DiagnosticControl> expect_diagnostic_control();
|
||||||
|
/// Parses a diagnostic_rule_name grammar element.
|
||||||
|
/// @return the parsed diagnostic rule name.
|
||||||
|
Expect<const ast::DiagnosticRuleName*> expect_diagnostic_rule_name();
|
||||||
|
|
||||||
/// Splits a peekable token into to parts filling in the peekable fields.
|
/// Splits a peekable token into to parts filling in the peekable fields.
|
||||||
/// @param lhs the token to set in the current position
|
/// @param lhs the token to set in the current position
|
||||||
|
@ -694,8 +697,11 @@ class ParserImpl {
|
||||||
/// Errors if the next token is not an identifier.
|
/// Errors if the next token is not an identifier.
|
||||||
/// Consumes the next token on match.
|
/// Consumes the next token on match.
|
||||||
/// @param use a description of what was being parsed if an error was raised
|
/// @param use a description of what was being parsed if an error was raised
|
||||||
|
/// @param kind a string describing the kind of identifier.
|
||||||
|
/// Examples: "identifier", "diagnostic name"
|
||||||
/// @returns the parsed identifier.
|
/// @returns the parsed identifier.
|
||||||
Expect<const ast::Identifier*> expect_ident(std::string_view use);
|
Expect<const ast::Identifier*> expect_ident(std::string_view use,
|
||||||
|
std::string_view kind = "identifier");
|
||||||
/// Parses a lexical block starting with the token `start` and ending with
|
/// Parses a lexical block starting with the token `start` and ending with
|
||||||
/// the token `end`. `body` is called to parse the lexical block body
|
/// the token `end`. `body` is called to parse the lexical block body
|
||||||
/// between the `start` and `end` tokens. If the `start` or `end` tokens
|
/// between the `start` and `end` tokens. If the `start` or `end` tokens
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
namespace tint::reader::wgsl {
|
namespace tint::reader::wgsl {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DiagnosticAttribute_Valid) {
|
TEST_F(ParserImplTest, DiagnosticAttribute_Name) {
|
||||||
auto p = parser("diagnostic(off, foo)");
|
auto p = parser("diagnostic(off, foo)");
|
||||||
auto a = p->attribute();
|
auto a = p->attribute();
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
@ -30,7 +30,22 @@ TEST_F(ParserImplTest, DiagnosticAttribute_Valid) {
|
||||||
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kOff);
|
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kOff);
|
||||||
auto* r = d->control.rule_name;
|
auto* r = d->control.rule_name;
|
||||||
ASSERT_NE(r, nullptr);
|
ASSERT_NE(r, nullptr);
|
||||||
ast::CheckIdentifier(r, "foo");
|
EXPECT_EQ(r->category, nullptr);
|
||||||
|
ast::CheckIdentifier(r->name, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, DiagnosticAttribute_CategoryName) {
|
||||||
|
auto p = parser("diagnostic(off, foo.bar)");
|
||||||
|
auto a = p->attribute();
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_TRUE(a.matched);
|
||||||
|
auto* d = a.value->As<ast::DiagnosticAttribute>();
|
||||||
|
ASSERT_NE(d, nullptr);
|
||||||
|
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kOff);
|
||||||
|
auto* r = d->control.rule_name;
|
||||||
|
ASSERT_NE(r, nullptr);
|
||||||
|
ast::CheckIdentifier(r->category, "foo");
|
||||||
|
ast::CheckIdentifier(r->name, "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace {
|
||||||
using SeverityPair = std::pair<std::string, builtin::DiagnosticSeverity>;
|
using SeverityPair = std::pair<std::string, builtin::DiagnosticSeverity>;
|
||||||
class DiagnosticControlParserTest : public ParserImplTestWithParam<SeverityPair> {};
|
class DiagnosticControlParserTest : public ParserImplTestWithParam<SeverityPair> {};
|
||||||
|
|
||||||
TEST_P(DiagnosticControlParserTest, DiagnosticControl_Valid) {
|
TEST_P(DiagnosticControlParserTest, DiagnosticControl_Name) {
|
||||||
auto& params = GetParam();
|
auto& params = GetParam();
|
||||||
auto p = parser("(" + params.first + ", foo)");
|
auto p = parser("(" + params.first + ", foo)");
|
||||||
auto e = p->expect_diagnostic_control();
|
auto e = p->expect_diagnostic_control();
|
||||||
|
@ -33,7 +33,21 @@ TEST_P(DiagnosticControlParserTest, DiagnosticControl_Valid) {
|
||||||
|
|
||||||
auto* r = e->rule_name;
|
auto* r = e->rule_name;
|
||||||
ASSERT_NE(r, nullptr);
|
ASSERT_NE(r, nullptr);
|
||||||
ast::CheckIdentifier(r, "foo");
|
EXPECT_EQ(r->category, nullptr);
|
||||||
|
ast::CheckIdentifier(r->name, "foo");
|
||||||
|
}
|
||||||
|
TEST_P(DiagnosticControlParserTest, DiagnosticControl_CategoryAndName) {
|
||||||
|
auto& params = GetParam();
|
||||||
|
auto p = parser("(" + params.first + ", foo.bar)");
|
||||||
|
auto e = p->expect_diagnostic_control();
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e->severity, params.second);
|
||||||
|
|
||||||
|
auto* r = e->rule_name;
|
||||||
|
ASSERT_NE(r, nullptr);
|
||||||
|
ast::CheckIdentifier(r->category, "foo");
|
||||||
|
ast::CheckIdentifier(r->name, "bar");
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(DiagnosticControlParserTest,
|
INSTANTIATE_TEST_SUITE_P(DiagnosticControlParserTest,
|
||||||
DiagnosticControlParserTest,
|
DiagnosticControlParserTest,
|
||||||
|
@ -43,7 +57,7 @@ INSTANTIATE_TEST_SUITE_P(DiagnosticControlParserTest,
|
||||||
SeverityPair{"info", builtin::DiagnosticSeverity::kInfo},
|
SeverityPair{"info", builtin::DiagnosticSeverity::kInfo},
|
||||||
SeverityPair{"off", builtin::DiagnosticSeverity::kOff}));
|
SeverityPair{"off", builtin::DiagnosticSeverity::kOff}));
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DiagnosticControl_Valid_TrailingComma) {
|
TEST_F(ParserImplTest, DiagnosticControl_Name_TrailingComma) {
|
||||||
auto p = parser("(error, foo,)");
|
auto p = parser("(error, foo,)");
|
||||||
auto e = p->expect_diagnostic_control();
|
auto e = p->expect_diagnostic_control();
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
|
@ -52,7 +66,21 @@ TEST_F(ParserImplTest, DiagnosticControl_Valid_TrailingComma) {
|
||||||
|
|
||||||
auto* r = e->rule_name;
|
auto* r = e->rule_name;
|
||||||
ASSERT_NE(r, nullptr);
|
ASSERT_NE(r, nullptr);
|
||||||
ast::CheckIdentifier(r, "foo");
|
EXPECT_EQ(r->category, nullptr);
|
||||||
|
ast::CheckIdentifier(r->name, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, DiagnosticControl_CategoryAndName_TrailingComma) {
|
||||||
|
auto p = parser("(error, foo.bar,)");
|
||||||
|
auto e = p->expect_diagnostic_control();
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
EXPECT_EQ(e->severity, builtin::DiagnosticSeverity::kError);
|
||||||
|
|
||||||
|
auto* r = e->rule_name;
|
||||||
|
ASSERT_NE(r, nullptr);
|
||||||
|
ast::CheckIdentifier(r->category, "foo");
|
||||||
|
ast::CheckIdentifier(r->name, "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DiagnosticControl_MissingOpenParen) {
|
TEST_F(ParserImplTest, DiagnosticControl_MissingOpenParen) {
|
||||||
|
@ -102,7 +130,15 @@ TEST_F(ParserImplTest, DiagnosticControl_MissingRuleName) {
|
||||||
auto e = p->expect_diagnostic_control();
|
auto e = p->expect_diagnostic_control();
|
||||||
EXPECT_TRUE(e.errored);
|
EXPECT_TRUE(e.errored);
|
||||||
EXPECT_TRUE(p->has_error());
|
EXPECT_TRUE(p->has_error());
|
||||||
EXPECT_EQ(p->error(), R"(1:6: expected identifier for diagnostic control)");
|
EXPECT_EQ(p->error(), R"(1:6: expected diagnostic rule name)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, DiagnosticControl_MissingRuleCategory) {
|
||||||
|
auto p = parser("(off,for.foo)");
|
||||||
|
auto e = p->expect_diagnostic_control();
|
||||||
|
EXPECT_TRUE(e.errored);
|
||||||
|
EXPECT_TRUE(p->has_error());
|
||||||
|
EXPECT_EQ(p->error(), R"(1:6: expected diagnostic rule category)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DiagnosticControl_InvalidRuleName) {
|
TEST_F(ParserImplTest, DiagnosticControl_InvalidRuleName) {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
namespace tint::reader::wgsl {
|
namespace tint::reader::wgsl {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DiagnosticDirective_Valid) {
|
TEST_F(ParserImplTest, DiagnosticDirective_Name) {
|
||||||
auto p = parser("diagnostic(off, foo);");
|
auto p = parser("diagnostic(off, foo);");
|
||||||
p->diagnostic_directive();
|
p->diagnostic_directive();
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
@ -33,7 +33,25 @@ TEST_F(ParserImplTest, DiagnosticDirective_Valid) {
|
||||||
|
|
||||||
auto* r = directive->control.rule_name;
|
auto* r = directive->control.rule_name;
|
||||||
ASSERT_NE(r, nullptr);
|
ASSERT_NE(r, nullptr);
|
||||||
ast::CheckIdentifier(r, "foo");
|
EXPECT_EQ(r->category, nullptr);
|
||||||
|
ast::CheckIdentifier(r->name, "foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, DiagnosticDirective_CategoryName) {
|
||||||
|
auto p = parser("diagnostic(off, foo.bar);");
|
||||||
|
p->diagnostic_directive();
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
auto& ast = p->builder().AST();
|
||||||
|
ASSERT_EQ(ast.DiagnosticDirectives().Length(), 1u);
|
||||||
|
auto* directive = ast.DiagnosticDirectives()[0];
|
||||||
|
EXPECT_EQ(directive->control.severity, builtin::DiagnosticSeverity::kOff);
|
||||||
|
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
|
||||||
|
EXPECT_EQ(ast.GlobalDeclarations()[0], directive);
|
||||||
|
|
||||||
|
auto* r = directive->control.rule_name;
|
||||||
|
ASSERT_NE(r, nullptr);
|
||||||
|
ast::CheckIdentifier(r->category, "foo");
|
||||||
|
ast::CheckIdentifier(r->name, "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, DiagnosticDirective_MissingSemicolon) {
|
TEST_F(ParserImplTest, DiagnosticDirective_MissingSemicolon) {
|
||||||
|
|
|
@ -101,7 +101,7 @@ static utils::Vector<const ast::Attribute*, 2> createAttributes(const Source& so
|
||||||
return {builder.Builtin(source, builtin::BuiltinValue::kPosition)};
|
return {builder.Builtin(source, builtin::BuiltinValue::kPosition)};
|
||||||
case AttributeKind::kDiagnostic:
|
case AttributeKind::kDiagnostic:
|
||||||
return {builder.DiagnosticAttribute(source, builtin::DiagnosticSeverity::kInfo,
|
return {builder.DiagnosticAttribute(source, builtin::DiagnosticSeverity::kInfo,
|
||||||
"chromium_unreachable_code")};
|
"chromium", "unreachable_code")};
|
||||||
case AttributeKind::kGroup:
|
case AttributeKind::kGroup:
|
||||||
return {builder.Group(source, 1_a)};
|
return {builder.Group(source, 1_a)};
|
||||||
case AttributeKind::kId:
|
case AttributeKind::kId:
|
||||||
|
|
|
@ -32,7 +32,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_DefaultSeverity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts);
|
Func("foo", {}, ty.void_(), stmts);
|
||||||
|
@ -42,7 +42,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaDirective) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaDirective) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kWarning, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kWarning, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts);
|
Func("foo", {}, ty.void_(), stmts);
|
||||||
|
@ -52,7 +52,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaDirective) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaDirective) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaDirective) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kInfo, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kInfo, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts);
|
Func("foo", {}, ty.void_(), stmts);
|
||||||
|
@ -62,7 +62,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaDirective) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaDirective) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaDirective) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts);
|
Func("foo", {}, ty.void_(), stmts);
|
||||||
|
@ -73,7 +73,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaDirective) {
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaAttribute) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaAttribute) {
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
@ -84,7 +84,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaAttribute) {
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaAttribute) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaAttribute) {
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
@ -95,7 +95,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaAttribute) {
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaAttribute) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaAttribute) {
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
@ -106,7 +106,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaAttribute) {
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaAttribute) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaAttribute) {
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
@ -116,15 +116,15 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaAttribute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective_OverriddenViaAttribute) {
|
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective_OverriddenViaAttribute) {
|
||||||
// diagnostic(error, chromium_unreachable_code);
|
// diagnostic(error, chromium.unreachable_code);
|
||||||
//
|
//
|
||||||
// @diagnostic(off, chromium_unreachable_code) fn foo() {
|
// @diagnostic(off, chromium.unreachable_code) fn foo() {
|
||||||
// return;
|
// return;
|
||||||
// return; // Should produce a warning
|
// return; // Should produce a warning
|
||||||
// }
|
// }
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium", "unreachable_code");
|
||||||
|
|
||||||
auto stmts = utils::Vector{Return(), Return()};
|
auto stmts = utils::Vector{Return(), Return()};
|
||||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||||
|
@ -134,7 +134,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective_Overridd
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||||
// @diagnostic(off, chromium_unreachable_code) fn foo() {
|
// @diagnostic(off, chromium.unreachable_code) fn foo() {
|
||||||
// return;
|
// return;
|
||||||
// return; // Should not produce a diagnostic
|
// return; // Should not produce a diagnostic
|
||||||
// }
|
// }
|
||||||
|
@ -144,13 +144,13 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||||
// return; // Should produce a warning (default severity)
|
// return; // Should produce a warning (default severity)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @diagnostic(info, chromium_unreachable_code) fn bar() {
|
// @diagnostic(info, chromium.unreachable_code) fn bar() {
|
||||||
// return;
|
// return;
|
||||||
// return; // Should produce an info
|
// return; // Should produce an info
|
||||||
// }
|
// }
|
||||||
{
|
{
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_code");
|
||||||
Func("foo", {}, ty.void_(),
|
Func("foo", {}, ty.void_(),
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
Return(),
|
Return(),
|
||||||
|
@ -167,7 +167,7 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium", "unreachable_code");
|
||||||
Func("zoo", {}, ty.void_(),
|
Func("zoo", {}, ty.void_(),
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
Return(),
|
Return(),
|
||||||
|
@ -182,17 +182,17 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
||||||
// fn foo() @diagnostic(off, chromium_unreachable_code) {
|
// fn foo() @diagnostic(off, chromium.unreachable_code) {
|
||||||
// {
|
// {
|
||||||
// return;
|
// return;
|
||||||
// return; // Should not produce a diagnostic
|
// return; // Should not produce a diagnostic
|
||||||
// }
|
// }
|
||||||
// @diagnostic(warning, chromium_unreachable_code) {
|
// @diagnostic(warning, chromium.unreachable_code) {
|
||||||
// if (true) @diagnostic(info, chromium_unreachable_code) {
|
// if (true) @diagnostic(info, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// return; // Should produce an info
|
// return; // Should produce an info
|
||||||
// } else {
|
// } else {
|
||||||
// while (true) @diagnostic(off, chromium_unreachable_code) {
|
// while (true) @diagnostic(off, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// return; // Should not produce a diagnostic
|
// return; // Should not produce a diagnostic
|
||||||
// }
|
// }
|
||||||
|
@ -203,7 +203,7 @@ TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
auto attr = [&](auto severity) {
|
auto attr = [&](auto severity) {
|
||||||
return utils::Vector{DiagnosticAttribute(severity, "chromium_unreachable_code")};
|
return utils::Vector{DiagnosticAttribute(severity, "chromium", "unreachable_code")};
|
||||||
};
|
};
|
||||||
Func("foo", {}, ty.void_(),
|
Func("foo", {}, ty.void_(),
|
||||||
utils::Vector{
|
utils::Vector{
|
||||||
|
@ -241,113 +241,157 @@ TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
||||||
78:87 warning: code is unreachable)");
|
78:87 warning: code is unreachable)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Directive) {
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedCoreRuleName_Directive) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_cod"));
|
DiagnosticRuleName(Source{{12, 34}}, "derivative_uniform"));
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_cod'
|
R"(12:34 warning: unrecognized diagnostic rule 'derivative_uniform'
|
||||||
Did you mean 'chromium_unreachable_code'?
|
Did you mean 'derivative_uniformity'?
|
||||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity')");
|
Possible values: 'derivative_uniformity')");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Attribute) {
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedCoreRuleName_Attribute) {
|
||||||
auto* attr = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
auto* attr = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_cod"));
|
DiagnosticRuleName(Source{{12, 34}}, "derivative_uniform"));
|
||||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_cod'
|
R"(12:34 warning: unrecognized diagnostic rule 'derivative_uniform'
|
||||||
Did you mean 'chromium_unreachable_code'?
|
Did you mean 'derivative_uniformity'?
|
||||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity')");
|
Possible values: 'derivative_uniformity')");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedChromiumRuleName_Directive) {
|
||||||
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_cod"));
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
R"(12:34 warning: unrecognized diagnostic rule 'chromium.unreachable_cod'
|
||||||
|
Did you mean 'chromium.unreachable_code'?
|
||||||
|
Possible values: 'chromium.unreachable_code')");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedChromiumRuleName_Attribute) {
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_cod"));
|
||||||
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(),
|
||||||
|
R"(12:34 warning: unrecognized diagnostic rule 'chromium.unreachable_cod'
|
||||||
|
Did you mean 'chromium.unreachable_code'?
|
||||||
|
Possible values: 'chromium.unreachable_code')");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedOtherRuleName_Directive) {
|
||||||
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
|
DiagnosticRuleName(Source{{12, 34}}, "unknown", "unreachable_cod"));
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ResolverDiagnosticControlTest, UnrecognizedOtherRuleName_Attribute) {
|
||||||
|
auto* attr =
|
||||||
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
|
DiagnosticRuleName(Source{{12, 34}}, "unknown", "unreachable_cod"));
|
||||||
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
||||||
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
EXPECT_EQ(r()->error(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Directive) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Directive) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Directive) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Directive) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kOff,
|
||||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
R"(56:78 error: conflicting diagnostic directive
|
R"(56:78 error: conflicting diagnostic directive
|
||||||
12:34 note: severity of 'chromium_unreachable_code' set to 'off' here)");
|
12:34 note: severity of 'chromium.unreachable_code' set to 'off' here)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameUnknownNameDifferentSeverity_Directive) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_SameUnknownNameDifferentSeverity_Directive) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_codes"));
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_codes"));
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff,
|
DiagnosticDirective(builtin::DiagnosticSeverity::kOff,
|
||||||
Ident(Source{{56, 78}}, "chromium_unreachable_codes"));
|
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_codes"));
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
R"(12:34 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||||
Did you mean 'chromium_unreachable_code'?
|
Did you mean 'chromium.unreachable_code'?
|
||||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
Possible values: 'chromium.unreachable_code'
|
||||||
56:78 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
56:78 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||||
Did you mean 'chromium_unreachable_code'?
|
Did you mean 'chromium.unreachable_code'?
|
||||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
Possible values: 'chromium.unreachable_code'
|
||||||
56:78 error: conflicting diagnostic directive
|
56:78 error: conflicting diagnostic directive
|
||||||
12:34 note: severity of 'chromium_unreachable_codes' set to 'off' here)");
|
12:34 note: severity of 'chromium.unreachable_codes' set to 'off' here)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_DifferentUnknownNameDifferentSeverity_Directive) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_DifferentUnknownNameDifferentSeverity_Directive) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_codes");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_codes");
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_codex");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_codex");
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Attribute) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Attribute) {
|
||||||
auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
auto* attr1 =
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
auto* attr2 =
|
||||||
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
|
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Attribute) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Attribute) {
|
||||||
auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
auto* attr1 =
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
auto* attr2 =
|
||||||
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
||||||
|
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
R"(56:78 error: conflicting diagnostic attribute
|
R"(56:78 error: conflicting diagnostic attribute
|
||||||
12:34 note: severity of 'chromium_unreachable_code' set to 'off' here)");
|
12:34 note: severity of 'chromium.unreachable_code' set to 'off' here)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameUnknownNameDifferentSeverity_Attribute) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_SameUnknownNameDifferentSeverity_Attribute) {
|
||||||
auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
auto* attr1 =
|
||||||
Ident(Source{{12, 34}}, "chromium_unreachable_codes"));
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||||
auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_codes"));
|
||||||
Ident(Source{{56, 78}}, "chromium_unreachable_codes"));
|
auto* attr2 =
|
||||||
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
||||||
|
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_codes"));
|
||||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(),
|
||||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
R"(12:34 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||||
Did you mean 'chromium_unreachable_code'?
|
Did you mean 'chromium.unreachable_code'?
|
||||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
Possible values: 'chromium.unreachable_code'
|
||||||
56:78 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
56:78 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||||
Did you mean 'chromium_unreachable_code'?
|
Did you mean 'chromium.unreachable_code'?
|
||||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
Possible values: 'chromium.unreachable_code'
|
||||||
56:78 error: conflicting diagnostic attribute
|
56:78 error: conflicting diagnostic attribute
|
||||||
12:34 note: severity of 'chromium_unreachable_codes' set to 'off' here)");
|
12:34 note: severity of 'chromium.unreachable_codes' set to 'off' here)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverDiagnosticControlTest, Conflict_DifferentUnknownNameDifferentSeverity_Attribute) {
|
TEST_F(ResolverDiagnosticControlTest, Conflict_DifferentUnknownNameDifferentSeverity_Attribute) {
|
||||||
auto* attr1 =
|
auto* attr1 =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium_unreachable_codes");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_codes");
|
||||||
auto* attr2 =
|
auto* attr2 =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_codex");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_codex");
|
||||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3466,15 +3466,33 @@ bool Resolver::InternalAttribute(const ast::InternalAttribute* attr) {
|
||||||
|
|
||||||
bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
|
bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
|
||||||
Mark(control.rule_name);
|
Mark(control.rule_name);
|
||||||
|
Mark(control.rule_name->name);
|
||||||
|
auto name = control.rule_name->name->symbol.Name();
|
||||||
|
|
||||||
auto rule_name = control.rule_name->symbol.Name();
|
if (control.rule_name->category) {
|
||||||
auto rule = builtin::ParseDiagnosticRule(rule_name);
|
Mark(control.rule_name->category);
|
||||||
if (rule != builtin::DiagnosticRule::kUndefined) {
|
if (control.rule_name->category->symbol.Name() == "chromium") {
|
||||||
|
auto rule = builtin::ParseChromiumDiagnosticRule(name);
|
||||||
|
if (rule != builtin::ChromiumDiagnosticRule::kUndefined) {
|
||||||
|
validator_.DiagnosticFilters().Set(rule, control.severity);
|
||||||
|
} else {
|
||||||
|
utils::StringStream ss;
|
||||||
|
ss << "unrecognized diagnostic rule 'chromium." << name << "'\n";
|
||||||
|
utils::SuggestAlternatives(name, builtin::kChromiumDiagnosticRuleStrings, ss,
|
||||||
|
"chromium.");
|
||||||
|
AddWarning(ss.str(), control.rule_name->source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rule = builtin::ParseCoreDiagnosticRule(name);
|
||||||
|
if (rule != builtin::CoreDiagnosticRule::kUndefined) {
|
||||||
validator_.DiagnosticFilters().Set(rule, control.severity);
|
validator_.DiagnosticFilters().Set(rule, control.severity);
|
||||||
} else {
|
} else {
|
||||||
utils::StringStream ss;
|
utils::StringStream ss;
|
||||||
ss << "unrecognized diagnostic rule '" << rule_name << "'\n";
|
ss << "unrecognized diagnostic rule '" << name << "'\n";
|
||||||
utils::SuggestAlternatives(rule_name, builtin::kDiagnosticRuleStrings, ss);
|
utils::SuggestAlternatives(name, builtin::kCoreDiagnosticRuleStrings, ss);
|
||||||
AddWarning(ss.str(), control.rule_name->source);
|
AddWarning(ss.str(), control.rule_name->source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1563,7 +1563,7 @@ class UniformityGraph {
|
||||||
builtin->Type() == builtin::Function::kTextureSampleCompare) {
|
builtin->Type() == builtin::Function::kTextureSampleCompare) {
|
||||||
// Get the severity of derivative uniformity violations in this context.
|
// Get the severity of derivative uniformity violations in this context.
|
||||||
auto severity = sem_.DiagnosticSeverity(
|
auto severity = sem_.DiagnosticSeverity(
|
||||||
call, builtin::DiagnosticRule::kDerivativeUniformity);
|
call, builtin::CoreDiagnosticRule::kDerivativeUniformity);
|
||||||
if (severity != builtin::DiagnosticSeverity::kOff) {
|
if (severity != builtin::DiagnosticSeverity::kOff) {
|
||||||
callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity};
|
callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity};
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,9 +159,9 @@ Validator::Validator(
|
||||||
atomic_composite_info_(atomic_composite_info),
|
atomic_composite_info_(atomic_composite_info),
|
||||||
valid_type_storage_layouts_(valid_type_storage_layouts) {
|
valid_type_storage_layouts_(valid_type_storage_layouts) {
|
||||||
// Set default severities for filterable diagnostic rules.
|
// Set default severities for filterable diagnostic rules.
|
||||||
diagnostic_filters_.Set(builtin::DiagnosticRule::kDerivativeUniformity,
|
diagnostic_filters_.Set(builtin::CoreDiagnosticRule::kDerivativeUniformity,
|
||||||
builtin::DiagnosticSeverity::kError);
|
builtin::DiagnosticSeverity::kError);
|
||||||
diagnostic_filters_.Set(builtin::DiagnosticRule::kChromiumUnreachableCode,
|
diagnostic_filters_.Set(builtin::ChromiumDiagnosticRule::kUnreachableCode,
|
||||||
builtin::DiagnosticSeverity::kWarning);
|
builtin::DiagnosticSeverity::kWarning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1417,7 +1417,7 @@ bool Validator::EvaluationStage(const sem::ValueExpression* expr,
|
||||||
bool Validator::Statements(utils::VectorRef<const ast::Statement*> stmts) const {
|
bool Validator::Statements(utils::VectorRef<const ast::Statement*> stmts) const {
|
||||||
for (auto* stmt : stmts) {
|
for (auto* stmt : stmts) {
|
||||||
if (!sem_.Get(stmt)->IsReachable()) {
|
if (!sem_.Get(stmt)->IsReachable()) {
|
||||||
if (!AddDiagnostic(builtin::DiagnosticRule::kChromiumUnreachableCode,
|
if (!AddDiagnostic(builtin::ChromiumDiagnosticRule::kUnreachableCode,
|
||||||
"code is unreachable", stmt->source)) {
|
"code is unreachable", stmt->source)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2530,9 +2530,12 @@ bool Validator::DiagnosticControls(utils::VectorRef<const ast::DiagnosticControl
|
||||||
const char* use) const {
|
const char* use) const {
|
||||||
// Make sure that no two diagnostic controls conflict.
|
// Make sure that no two diagnostic controls conflict.
|
||||||
// They conflict if the rule name is the same and the severity is different.
|
// They conflict if the rule name is the same and the severity is different.
|
||||||
utils::Hashmap<Symbol, const ast::DiagnosticControl*, 8> diagnostics;
|
utils::Hashmap<std::pair<Symbol, Symbol>, const ast::DiagnosticControl*, 8> diagnostics;
|
||||||
for (auto* dc : controls) {
|
for (auto* dc : controls) {
|
||||||
auto diag_added = diagnostics.Add(dc->rule_name->symbol, dc);
|
auto category = dc->rule_name->category ? dc->rule_name->category->symbol : Symbol();
|
||||||
|
auto name = dc->rule_name->name->symbol;
|
||||||
|
|
||||||
|
auto diag_added = diagnostics.Add(std::make_pair(category, name), dc);
|
||||||
if (!diag_added && (*diag_added.value)->severity != dc->severity) {
|
if (!diag_added && (*diag_added.value)->severity != dc->severity) {
|
||||||
{
|
{
|
||||||
utils::StringStream ss;
|
utils::StringStream ss;
|
||||||
|
@ -2541,8 +2544,8 @@ bool Validator::DiagnosticControls(utils::VectorRef<const ast::DiagnosticControl
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
utils::StringStream ss;
|
utils::StringStream ss;
|
||||||
ss << "severity of '" << dc->rule_name->symbol.Name() << "' set to '"
|
ss << "severity of '" << dc->rule_name->String() << "' set to '" << dc->severity
|
||||||
<< dc->severity << "' here";
|
<< "' here";
|
||||||
AddNote(ss.str(), (*diag_added.value)->rule_name->source);
|
AddNote(ss.str(), (*diag_added.value)->rule_name->source);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -23,27 +23,27 @@ namespace {
|
||||||
|
|
||||||
class DiagnosticSeverityTest : public TestHelper {
|
class DiagnosticSeverityTest : public TestHelper {
|
||||||
protected:
|
protected:
|
||||||
/// Create a program with two functions, setting the severity for "chromium_unreachable_code"
|
/// 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
|
/// using an attribute. Test that we correctly track the severity of the filter for the
|
||||||
/// functions and the statements with them.
|
/// functions and the statements with them.
|
||||||
/// @param global_severity the global severity of the "chromium_unreachable_code" filter
|
/// @param global_severity the global severity of the "chromium.unreachable_code" filter
|
||||||
void Run(builtin::DiagnosticSeverity global_severity) {
|
void Run(builtin::DiagnosticSeverity global_severity) {
|
||||||
// @diagnostic(off, chromium_unreachable_code)
|
// @diagnostic(off, chromium.unreachable_code)
|
||||||
// fn foo() {
|
// fn foo() {
|
||||||
// @diagnostic(info, chromium_unreachable_code) {
|
// @diagnostic(info, chromium.unreachable_code) {
|
||||||
// @diagnostic(error, chromium_unreachable_code)
|
// @diagnostic(error, chromium.unreachable_code)
|
||||||
// if (true) @diagnostic(warning, chromium_unreachable_code) {
|
// if (true) @diagnostic(warning, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// } else if (false) {
|
// } else if (false) {
|
||||||
// return;
|
// return;
|
||||||
// } else @diagnostic(info, chromium_unreachable_code) {
|
// } else @diagnostic(info, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// return;
|
// return;
|
||||||
//
|
//
|
||||||
// @diagnostic(error, chromium_unreachable_code)
|
// @diagnostic(error, chromium.unreachable_code)
|
||||||
// switch (42) @diagnostic(off, chromium_unreachable_code) {
|
// switch (42) @diagnostic(off, chromium.unreachable_code) {
|
||||||
// case 0 @diagnostic(warning, chromium_unreachable_code) {
|
// case 0 @diagnostic(warning, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// default {
|
// default {
|
||||||
|
@ -51,21 +51,21 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @diagnostic(error, chromium_unreachable_code)
|
// @diagnostic(error, chromium.unreachable_code)
|
||||||
// for (var i = 0; false; i++) @diagnostic(warning, chromium_unreachable_code) {
|
// for (var i = 0; false; i++) @diagnostic(warning, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @diagnostic(warning, chromium_unreachable_code)
|
// @diagnostic(warning, chromium.unreachable_code)
|
||||||
// loop @diagnostic(off, chromium_unreachable_code) {
|
// loop @diagnostic(off, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// continuing @diagnostic(info, chromium_unreachable_code) {
|
// continuing @diagnostic(info, chromium.unreachable_code) {
|
||||||
// break if true;
|
// break if true;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @diagnostic(error, chromium_unreachable_code)
|
// @diagnostic(error, chromium.unreachable_code)
|
||||||
// while (false) @diagnostic(warning, chromium_unreachable_code) {
|
// while (false) @diagnostic(warning, chromium.unreachable_code) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -74,7 +74,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
// fn bar() {
|
// fn bar() {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
auto rule = builtin::DiagnosticRule::kChromiumUnreachableCode;
|
auto rule = builtin::ChromiumDiagnosticRule::kUnreachableCode;
|
||||||
auto func_severity = builtin::DiagnosticSeverity::kOff;
|
auto func_severity = builtin::DiagnosticSeverity::kOff;
|
||||||
auto block_severity = builtin::DiagnosticSeverity::kInfo;
|
auto block_severity = builtin::DiagnosticSeverity::kInfo;
|
||||||
auto if_severity = builtin::DiagnosticSeverity::kError;
|
auto if_severity = builtin::DiagnosticSeverity::kError;
|
||||||
|
@ -91,7 +91,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
auto while_severity = builtin::DiagnosticSeverity::kError;
|
auto while_severity = builtin::DiagnosticSeverity::kError;
|
||||||
auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
|
auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
|
||||||
auto attr = [&](auto severity) {
|
auto attr = [&](auto severity) {
|
||||||
return utils::Vector{DiagnosticAttribute(severity, "chromium_unreachable_code")};
|
return utils::Vector{DiagnosticAttribute(severity, "chromium", "unreachable_code")};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto* return_foo_if = Return();
|
auto* return_foo_if = Return();
|
||||||
|
@ -123,7 +123,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
attr(while_severity));
|
attr(while_severity));
|
||||||
auto* block_1 =
|
auto* block_1 =
|
||||||
Block(utils::Vector{if_foo, return_foo_block, swtch, fl, l, wl}, attr(block_severity));
|
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* func_attr = DiagnosticAttribute(func_severity, "chromium", "unreachable_code");
|
||||||
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{block_1}, utils::Vector{func_attr});
|
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{block_1}, utils::Vector{func_attr});
|
||||||
|
|
||||||
auto* return_bar = Return();
|
auto* return_bar = Return();
|
||||||
|
@ -173,7 +173,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(DiagnosticSeverityTest, WithDirective) {
|
TEST_F(DiagnosticSeverityTest, WithDirective) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||||
Run(builtin::DiagnosticSeverity::kError);
|
Run(builtin::DiagnosticSeverity::kError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1289,10 +1289,16 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](const ast::DiagnosticAttribute* diagnostic) {
|
[&](const ast::DiagnosticAttribute* diagnostic) {
|
||||||
preserved_identifiers.Add(diagnostic->control.rule_name);
|
if (auto* category = diagnostic->control.rule_name->category) {
|
||||||
|
preserved_identifiers.Add(category);
|
||||||
|
}
|
||||||
|
preserved_identifiers.Add(diagnostic->control.rule_name->name);
|
||||||
},
|
},
|
||||||
[&](const ast::DiagnosticDirective* diagnostic) {
|
[&](const ast::DiagnosticDirective* diagnostic) {
|
||||||
preserved_identifiers.Add(diagnostic->control.rule_name);
|
if (auto* category = diagnostic->control.rule_name->category) {
|
||||||
|
preserved_identifiers.Add(category);
|
||||||
|
}
|
||||||
|
preserved_identifiers.Add(diagnostic->control.rule_name->name);
|
||||||
},
|
},
|
||||||
[&](const ast::IdentifierExpression* expr) {
|
[&](const ast::IdentifierExpression* expr) {
|
||||||
Switch(
|
Switch(
|
||||||
|
|
|
@ -192,9 +192,9 @@ fn tint_symbol() {
|
||||||
EXPECT_THAT(data->remappings, ContainerEq(expected_remappings));
|
EXPECT_THAT(data->remappings, ContainerEq(expected_remappings));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RenamerTest, PreserveDiagnosticControls) {
|
TEST_F(RenamerTest, PreserveCoreDiagnosticRuleName) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
diagnostic(off, unreachable_code);
|
diagnostic(off, chromium.unreachable_code);
|
||||||
|
|
||||||
@diagnostic(off, derivative_uniformity)
|
@diagnostic(off, derivative_uniformity)
|
||||||
@fragment
|
@fragment
|
||||||
|
@ -208,7 +208,7 @@ fn entry(@location(0) value : f32) -> @location(0) f32 {
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto* expect = R"(
|
auto* expect = R"(
|
||||||
diagnostic(off, unreachable_code);
|
diagnostic(off, chromium.unreachable_code);
|
||||||
|
|
||||||
@diagnostic(off, derivative_uniformity) @fragment
|
@diagnostic(off, derivative_uniformity) @fragment
|
||||||
fn tint_symbol(@location(0) tint_symbol_1 : f32) -> @location(0) f32 {
|
fn tint_symbol(@location(0) tint_symbol_1 : f32) -> @location(0) f32 {
|
||||||
|
|
|
@ -134,7 +134,15 @@ struct Hasher<std::tuple<TYPES...>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Hasher specialization for std::tuple
|
/// Hasher specialization for std::pair
|
||||||
|
template <typename A, typename B>
|
||||||
|
struct Hasher<std::pair<A, B>> {
|
||||||
|
/// @param tuple the tuple to hash
|
||||||
|
/// @returns a hash of the tuple
|
||||||
|
size_t operator()(const std::pair<A, B>& tuple) const { return std::apply(Hash<A, B>, tuple); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Hasher specialization for std::variant
|
||||||
template <typename... TYPES>
|
template <typename... TYPES>
|
||||||
struct Hasher<std::variant<TYPES...>> {
|
struct Hasher<std::variant<TYPES...>> {
|
||||||
/// @param variant the variant to hash
|
/// @param variant the variant to hash
|
||||||
|
|
|
@ -50,7 +50,8 @@ size_t Distance(std::string_view str_a, std::string_view str_b) {
|
||||||
|
|
||||||
void SuggestAlternatives(std::string_view got,
|
void SuggestAlternatives(std::string_view got,
|
||||||
Slice<char const* const> strings,
|
Slice<char const* const> strings,
|
||||||
utils::StringStream& ss) {
|
utils::StringStream& ss,
|
||||||
|
std::string_view prefix /* = "" */) {
|
||||||
// If the string typed was within kSuggestionDistance of one of the possible enum values,
|
// If the string typed was within kSuggestionDistance of one of the possible enum values,
|
||||||
// suggest that. Don't bother with suggestions if the string was extremely long.
|
// suggest that. Don't bother with suggestions if the string was extremely long.
|
||||||
constexpr size_t kSuggestionDistance = 5;
|
constexpr size_t kSuggestionDistance = 5;
|
||||||
|
@ -66,7 +67,7 @@ void SuggestAlternatives(std::string_view got,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (candidate) {
|
if (candidate) {
|
||||||
ss << "Did you mean '" << candidate << "'?\n";
|
ss << "Did you mean '" << prefix << candidate << "'?\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ void SuggestAlternatives(std::string_view got,
|
||||||
if (str != strings[0]) {
|
if (str != strings[0]) {
|
||||||
ss << ", ";
|
ss << ", ";
|
||||||
}
|
}
|
||||||
ss << "'" << str << "'";
|
ss << "'" << prefix << str << "'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,9 +72,11 @@ size_t Distance(std::string_view a, std::string_view b);
|
||||||
/// @param got the unrecognized string
|
/// @param got the unrecognized string
|
||||||
/// @param strings the list of possible values
|
/// @param strings the list of possible values
|
||||||
/// @param ss the stream to write the suggest and list of possible values to
|
/// @param ss the stream to write the suggest and list of possible values to
|
||||||
|
/// @param prefix the prefix to apply to the strings when printing (optional)
|
||||||
void SuggestAlternatives(std::string_view got,
|
void SuggestAlternatives(std::string_view got,
|
||||||
Slice<char const* const> strings,
|
Slice<char const* const> strings,
|
||||||
utils::StringStream& ss);
|
utils::StringStream& ss,
|
||||||
|
std::string_view prefix = "");
|
||||||
|
|
||||||
} // namespace tint::utils
|
} // namespace tint::utils
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ void GeneratorImpl::Generate() {
|
||||||
|
|
||||||
void GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic) {
|
void GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic) {
|
||||||
line() << "DiagnosticControl [severity: " << diagnostic.severity
|
line() << "DiagnosticControl [severity: " << diagnostic.severity
|
||||||
<< ", rule: " << diagnostic.rule_name->symbol.Name() << "]";
|
<< ", rule: " << diagnostic.rule_name->String() << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
|
void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
|
||||||
|
|
|
@ -82,8 +82,7 @@ void GeneratorImpl::Generate() {
|
||||||
|
|
||||||
void GeneratorImpl::EmitDiagnosticControl(utils::StringStream& out,
|
void GeneratorImpl::EmitDiagnosticControl(utils::StringStream& out,
|
||||||
const ast::DiagnosticControl& diagnostic) {
|
const ast::DiagnosticControl& diagnostic) {
|
||||||
out << "diagnostic(" << diagnostic.severity << ", " << diagnostic.rule_name->symbol.Name()
|
out << "diagnostic(" << diagnostic.severity << ", " << diagnostic.rule_name->String() << ")";
|
||||||
<< ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
|
void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
|
||||||
|
|
|
@ -22,25 +22,25 @@ namespace {
|
||||||
using WgslGeneratorImplTest = TestHelper;
|
using WgslGeneratorImplTest = TestHelper;
|
||||||
|
|
||||||
TEST_F(WgslGeneratorImplTest, Emit_DiagnosticDirective) {
|
TEST_F(WgslGeneratorImplTest, Emit_DiagnosticDirective) {
|
||||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
gen.Generate();
|
gen.Generate();
|
||||||
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
||||||
EXPECT_EQ(gen.result(), R"(diagnostic(error, chromium_unreachable_code);
|
EXPECT_EQ(gen.result(), R"(diagnostic(error, chromium.unreachable_code);
|
||||||
|
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WgslGeneratorImplTest, Emit_DiagnosticAttribute) {
|
TEST_F(WgslGeneratorImplTest, Emit_DiagnosticAttribute) {
|
||||||
auto* attr =
|
auto* attr =
|
||||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
||||||
|
|
||||||
GeneratorImpl& gen = Build();
|
GeneratorImpl& gen = Build();
|
||||||
gen.Generate();
|
gen.Generate();
|
||||||
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
|
||||||
EXPECT_EQ(gen.result(), R"(@diagnostic(error, chromium_unreachable_code)
|
EXPECT_EQ(gen.result(), R"(@diagnostic(error, chromium.unreachable_code)
|
||||||
fn foo() {
|
fn foo() {
|
||||||
}
|
}
|
||||||
)");
|
)");
|
||||||
|
|
Loading…
Reference in New Issue