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_control.h",
|
||||
"ast/diagnostic_directive.h",
|
||||
"ast/diagnostic_rule_name.h",
|
||||
"ast/disable_validation_attribute.h",
|
||||
"ast/discard_statement.h",
|
||||
"ast/enable.h",
|
||||
|
@ -559,6 +560,7 @@ libtint_source_set("libtint_ast_src") {
|
|||
"ast/diagnostic_attribute.cc",
|
||||
"ast/diagnostic_control.cc",
|
||||
"ast/diagnostic_directive.cc",
|
||||
"ast/diagnostic_rule_name.cc",
|
||||
"ast/disable_validation_attribute.cc",
|
||||
"ast/discard_statement.cc",
|
||||
"ast/enable.cc",
|
||||
|
@ -1291,6 +1293,7 @@ if (tint_build_unittests) {
|
|||
"ast/diagnostic_attribute_test.cc",
|
||||
"ast/diagnostic_control_test.cc",
|
||||
"ast/diagnostic_directive_test.cc",
|
||||
"ast/diagnostic_rule_name_test.cc",
|
||||
"ast/discard_statement_test.cc",
|
||||
"ast/enable_test.cc",
|
||||
"ast/float_literal_expression_test.cc",
|
||||
|
|
|
@ -126,6 +126,8 @@ list(APPEND TINT_LIB_SRCS
|
|||
ast/diagnostic_control.h
|
||||
ast/diagnostic_directive.cc
|
||||
ast/diagnostic_directive.h
|
||||
ast/diagnostic_rule_name.cc
|
||||
ast/diagnostic_rule_name.h
|
||||
ast/disable_validation_attribute.cc
|
||||
ast/disable_validation_attribute.h
|
||||
ast/discard_statement.cc
|
||||
|
@ -845,6 +847,7 @@ if(TINT_BUILD_TESTS)
|
|||
ast/diagnostic_attribute_test.cc
|
||||
ast/diagnostic_control_test.cc
|
||||
ast/diagnostic_directive_test.cc
|
||||
ast/diagnostic_rule_name_test.cc
|
||||
ast/discard_statement_test.cc
|
||||
ast/enable_test.cc
|
||||
ast/float_literal_expression_test.cc
|
||||
|
|
|
@ -20,12 +20,20 @@ namespace {
|
|||
using namespace tint::number_suffixes; // NOLINT
|
||||
using DiagnosticAttributeTest = TestHelper;
|
||||
|
||||
TEST_F(DiagnosticAttributeTest, Creation) {
|
||||
auto* name = Ident("foo");
|
||||
auto* d = DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, name);
|
||||
TEST_F(DiagnosticAttributeTest, Name) {
|
||||
auto* d = DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "foo");
|
||||
EXPECT_EQ(d->Name(), "diagnostic");
|
||||
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
|
||||
|
|
|
@ -24,13 +24,10 @@ namespace tint::ast {
|
|||
|
||||
DiagnosticControl::DiagnosticControl() = default;
|
||||
|
||||
DiagnosticControl::DiagnosticControl(builtin::DiagnosticSeverity sev, const Identifier* rule)
|
||||
DiagnosticControl::DiagnosticControl(builtin::DiagnosticSeverity sev,
|
||||
const DiagnosticRuleName* rule)
|
||||
: severity(sev), rule_name(rule) {
|
||||
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;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
class Identifier;
|
||||
class DiagnosticRuleName;
|
||||
} // namespace tint::ast
|
||||
|
||||
namespace tint::ast {
|
||||
|
@ -37,16 +37,16 @@ struct DiagnosticControl {
|
|||
/// Constructor
|
||||
/// @param sev the diagnostic severity
|
||||
/// @param rule the diagnostic rule name
|
||||
DiagnosticControl(builtin::DiagnosticSeverity sev, const Identifier* rule);
|
||||
DiagnosticControl(builtin::DiagnosticSeverity sev, const DiagnosticRuleName* rule);
|
||||
|
||||
/// Move constructor
|
||||
DiagnosticControl(DiagnosticControl&&);
|
||||
|
||||
/// The diagnostic severity control.
|
||||
builtin::DiagnosticSeverity severity;
|
||||
builtin::DiagnosticSeverity severity = builtin::DiagnosticSeverity::kUndefined;
|
||||
|
||||
/// The diagnostic rule name.
|
||||
const Identifier* rule_name;
|
||||
const DiagnosticRuleName* rule_name = nullptr;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
|
|
@ -24,12 +24,11 @@ namespace {
|
|||
|
||||
using DiagnosticControlTest = TestHelper;
|
||||
|
||||
TEST_F(DiagnosticControlTest, Assert_RuleNotTemplated) {
|
||||
TEST_F(DiagnosticControlTest, Assert_RuleNotNull) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
DiagnosticControl control(builtin::DiagnosticSeverity::kWarning,
|
||||
b.Ident("name", "a", "b", "c"));
|
||||
DiagnosticControl control(builtin::DiagnosticSeverity::kWarning, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
|
|
@ -34,4 +34,5 @@ const DiagnosticDirective* DiagnosticDirective::Clone(CloneContext* ctx) const {
|
|||
DiagnosticControl dc(control.severity, rule);
|
||||
return ctx->dst->create<DiagnosticDirective>(src, std::move(dc));
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
|
|
@ -21,15 +21,28 @@ namespace {
|
|||
|
||||
using DiagnosticDirectiveTest = TestHelper;
|
||||
|
||||
TEST_F(DiagnosticDirectiveTest, Creation) {
|
||||
auto* diag = DiagnosticDirective(Source{{{10, 5}, {10, 15}}},
|
||||
builtin::DiagnosticSeverity::kWarning, "foo");
|
||||
EXPECT_EQ(diag->source.range.begin.line, 10u);
|
||||
EXPECT_EQ(diag->source.range.begin.column, 5u);
|
||||
EXPECT_EQ(diag->source.range.end.line, 10u);
|
||||
EXPECT_EQ(diag->source.range.end.column, 15u);
|
||||
EXPECT_EQ(diag->control.severity, builtin::DiagnosticSeverity::kWarning);
|
||||
CheckIdentifier(diag->control.rule_name, "foo");
|
||||
TEST_F(DiagnosticDirectiveTest, Name) {
|
||||
auto* d = DiagnosticDirective(Source{{{10, 5}, {10, 15}}},
|
||||
builtin::DiagnosticSeverity::kWarning, "foo");
|
||||
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);
|
||||
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
|
||||
|
|
|
@ -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.
|
||||
// See also fuzzers/tint_ast_clone_fuzzer.cc for further coverage of cloning.
|
||||
Source::File file("test.wgsl", R"(enable f16;
|
||||
diagnostic(off, chromium_unreachable_code);
|
||||
diagnostic(off, chromium.unreachable_code);
|
||||
|
||||
struct S0 {
|
||||
@size(4)
|
||||
|
@ -65,7 +65,7 @@ fn f0(p0 : bool) -> f32 {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
@diagnostic(warning, chromium_unreachable_code)
|
||||
@diagnostic(warning, chromium.unreachable_code)
|
||||
fn f1(p0 : f32, p1 : i32) -> f32 {
|
||||
var l0 : i32 = 3;
|
||||
var l1 : f32 = 8.0;
|
||||
|
|
|
@ -28,29 +28,45 @@
|
|||
|
||||
namespace tint::builtin {
|
||||
|
||||
/// ParseDiagnosticRule parses a DiagnosticRule from a string.
|
||||
/// ParseCoreDiagnosticRule parses a CoreDiagnosticRule from a string.
|
||||
/// @param str the string to parse
|
||||
/// @returns the parsed enum, or DiagnosticRule::kUndefined if the string could not be parsed.
|
||||
DiagnosticRule ParseDiagnosticRule(std::string_view str) {
|
||||
if (str == "chromium_unreachable_code") {
|
||||
return DiagnosticRule::kChromiumUnreachableCode;
|
||||
}
|
||||
/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
|
||||
CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str) {
|
||||
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) {
|
||||
case DiagnosticRule::kUndefined:
|
||||
case CoreDiagnosticRule::kUndefined:
|
||||
return out << "undefined";
|
||||
case DiagnosticRule::kChromiumUnreachableCode:
|
||||
return out << "chromium_unreachable_code";
|
||||
case DiagnosticRule::kDerivativeUniformity:
|
||||
case CoreDiagnosticRule::kDerivativeUniformity:
|
||||
return out << "derivative_uniformity";
|
||||
}
|
||||
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
|
||||
|
|
|
@ -18,8 +18,12 @@ See:
|
|||
|
||||
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
|
||||
|
|
|
@ -24,33 +24,56 @@
|
|||
#define SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "src/tint/utils/string_stream.h"
|
||||
|
||||
namespace tint::builtin {
|
||||
|
||||
/// The diagnostic rule.
|
||||
enum class DiagnosticRule {
|
||||
/// WGSL core diagnostic rules.
|
||||
enum class CoreDiagnosticRule {
|
||||
kUndefined,
|
||||
kChromiumUnreachableCode,
|
||||
kDerivativeUniformity,
|
||||
};
|
||||
|
||||
/// @param out the stream to write to
|
||||
/// @param value the DiagnosticRule
|
||||
/// @param value the CoreDiagnosticRule
|
||||
/// @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
|
||||
/// @returns the parsed enum, or DiagnosticRule::kUndefined if the string could not be parsed.
|
||||
DiagnosticRule ParseDiagnosticRule(std::string_view str);
|
||||
/// @returns the parsed enum, or CoreDiagnosticRule::kUndefined if the string could not be parsed.
|
||||
CoreDiagnosticRule ParseCoreDiagnosticRule(std::string_view str);
|
||||
|
||||
constexpr const char* kDiagnosticRuleStrings[] = {
|
||||
"chromium_unreachable_code",
|
||||
constexpr const char* kCoreDiagnosticRuleStrings[] = {
|
||||
"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
|
||||
|
||||
#endif // SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
||||
|
|
|
@ -14,13 +14,20 @@ See:
|
|||
#define SRC_TINT_BUILTIN_DIAGNOSTIC_RULE_H_
|
||||
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "src/tint/utils/string_stream.h"
|
||||
|
||||
namespace tint::builtin {
|
||||
|
||||
/// The diagnostic rule.
|
||||
{{ Eval "DeclareEnum" (Sem.Enum "diagnostic_rule") }}
|
||||
/// WGSL core diagnostic rules.
|
||||
{{ 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
|
||||
|
||||
|
|
|
@ -29,23 +29,36 @@
|
|||
namespace tint::builtin {
|
||||
namespace {
|
||||
|
||||
void DiagnosticRuleParser(::benchmark::State& state) {
|
||||
void CoreDiagnosticRuleParser(::benchmark::State& state) {
|
||||
const char* kStrings[] = {
|
||||
"chromium_unrachaccle_code", "clromium_unreachab3_oe", "chromium_unreachable_Vode",
|
||||
"chromium_unreachable_code", "chro1ium_unreachable_code", "chromium_unreJchableqqcde",
|
||||
"chromium77unreallhable_code", "dqqrvatiHHe_uniforppity", "deriatcv_nvformity",
|
||||
"derivatbe_unGformity", "derivative_uniformity", "derivative_iinifvrmity",
|
||||
"derivat8WWe_uniformity", "drivaxxive_uniformity",
|
||||
"deriative_unccformity", "dlivative_3iformiy", "derivative_uniforVity",
|
||||
"derivative_uniformity", "derivative_uniform1ty", "derivativeJunifqrmity",
|
||||
"derivative_unifllrmit77",
|
||||
};
|
||||
for (auto _ : state) {
|
||||
for (auto* str : kStrings) {
|
||||
auto result = ParseDiagnosticRule(str);
|
||||
auto result = ParseCoreDiagnosticRule(str);
|
||||
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 tint::builtin
|
||||
|
|
|
@ -19,7 +19,9 @@ See:
|
|||
namespace tint::builtin {
|
||||
namespace {
|
||||
|
||||
{{ Eval "BenchmarkParseEnum" (Sem.Enum "diagnostic_rule")}}
|
||||
{{ Eval "BenchmarkParseEnum" (Sem.Enum "core_diagnostic_rule")}}
|
||||
|
||||
{{ Eval "BenchmarkParseEnum" (Sem.Enum "chromium_diagnostic_rule")}}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::builtin
|
||||
|
|
|
@ -29,13 +29,13 @@
|
|||
namespace tint::builtin {
|
||||
namespace {
|
||||
|
||||
namespace diagnostic_rule_tests {
|
||||
namespace core_diagnostic_rule_tests {
|
||||
|
||||
namespace parse_print_tests {
|
||||
|
||||
struct Case {
|
||||
const char* string;
|
||||
DiagnosticRule value;
|
||||
CoreDiagnosticRule value;
|
||||
};
|
||||
|
||||
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[] = {
|
||||
{"chromium_unreachable_code", DiagnosticRule::kChromiumUnreachableCode},
|
||||
{"derivative_uniformity", DiagnosticRule::kDerivativeUniformity},
|
||||
{"derivative_uniformity", CoreDiagnosticRule::kDerivativeUniformity},
|
||||
};
|
||||
|
||||
static constexpr Case kInvalidCases[] = {
|
||||
{"chromium_unrachaccle_code", DiagnosticRule::kUndefined},
|
||||
{"clromium_unreachab3_oe", DiagnosticRule::kUndefined},
|
||||
{"chromium_unreachable_Vode", DiagnosticRule::kUndefined},
|
||||
{"derivative_uniform1ty", DiagnosticRule::kUndefined},
|
||||
{"derivativeJunifqrmity", DiagnosticRule::kUndefined},
|
||||
{"derivative_unifllrmit77", DiagnosticRule::kUndefined},
|
||||
{"deriative_unccformity", CoreDiagnosticRule::kUndefined},
|
||||
{"dlivative_3iformiy", CoreDiagnosticRule::kUndefined},
|
||||
{"derivative_uniforVity", CoreDiagnosticRule::kUndefined},
|
||||
};
|
||||
|
||||
using DiagnosticRuleParseTest = testing::TestWithParam<Case>;
|
||||
using CoreDiagnosticRuleParseTest = testing::TestWithParam<Case>;
|
||||
|
||||
TEST_P(DiagnosticRuleParseTest, Parse) {
|
||||
TEST_P(CoreDiagnosticRuleParseTest, Parse) {
|
||||
const char* string = GetParam().string;
|
||||
DiagnosticRule expect = GetParam().value;
|
||||
EXPECT_EQ(expect, ParseDiagnosticRule(string));
|
||||
CoreDiagnosticRule expect = GetParam().value;
|
||||
EXPECT_EQ(expect, ParseCoreDiagnosticRule(string));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(ValidCases, DiagnosticRuleParseTest, testing::ValuesIn(kValidCases));
|
||||
INSTANTIATE_TEST_SUITE_P(InvalidCases, DiagnosticRuleParseTest, testing::ValuesIn(kInvalidCases));
|
||||
INSTANTIATE_TEST_SUITE_P(ValidCases, CoreDiagnosticRuleParseTest, testing::ValuesIn(kValidCases));
|
||||
INSTANTIATE_TEST_SUITE_P(InvalidCases,
|
||||
CoreDiagnosticRuleParseTest,
|
||||
testing::ValuesIn(kInvalidCases));
|
||||
|
||||
using DiagnosticRulePrintTest = testing::TestWithParam<Case>;
|
||||
using CoreDiagnosticRulePrintTest = testing::TestWithParam<Case>;
|
||||
|
||||
TEST_P(DiagnosticRulePrintTest, Print) {
|
||||
DiagnosticRule value = GetParam().value;
|
||||
TEST_P(CoreDiagnosticRulePrintTest, Print) {
|
||||
CoreDiagnosticRule value = GetParam().value;
|
||||
const char* expect = GetParam().string;
|
||||
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 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 tint::builtin
|
||||
|
|
|
@ -19,11 +19,17 @@ See:
|
|||
namespace tint::builtin {
|
||||
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 tint::builtin
|
||||
|
|
|
@ -41,11 +41,15 @@ enum builtin_value {
|
|||
}
|
||||
|
||||
// https://gpuweb.github.io/gpuweb/wgsl/#filterable-triggering-rules
|
||||
enum diagnostic_rule {
|
||||
enum core_diagnostic_rule {
|
||||
// Rules defined in the spec.
|
||||
derivative_uniformity
|
||||
}
|
||||
|
||||
// chromium-specific diagnostics
|
||||
enum chromium_diagnostic_rule {
|
||||
// Chromium specific rules not defined in the spec.
|
||||
chromium_unreachable_code
|
||||
unreachable_code
|
||||
}
|
||||
|
||||
// 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_control.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/discard_statement.h"
|
||||
#include "src/tint/ast/enable.h"
|
||||
|
@ -3752,57 +3753,129 @@ class ProgramBuilder {
|
|||
validation);
|
||||
}
|
||||
|
||||
/// Creates an ast::DiagnosticAttribute
|
||||
/// @param source the source information
|
||||
/// @param severity the diagnostic severity control
|
||||
/// @param rule_name the diagnostic rule name
|
||||
/// @returns the diagnostic attribute pointer
|
||||
/// Passthrough overload
|
||||
/// @param name the diagnostic rule name
|
||||
/// @returns @p name
|
||||
const ast::DiagnosticRuleName* DiagnosticRuleName(const ast::DiagnosticRuleName* name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
/// Creates an ast::DiagnosticRuleName
|
||||
/// @param name the diagnostic rule name
|
||||
/// @returns the diagnostic rule name
|
||||
template <typename NAME>
|
||||
const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source,
|
||||
builtin::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
const ast::DiagnosticRuleName* DiagnosticRuleName(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>(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>(
|
||||
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
|
||||
/// @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
|
||||
template <typename NAME>
|
||||
template <typename... RULE_ARGS>
|
||||
const ast::DiagnosticAttribute* DiagnosticAttribute(builtin::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
RULE_ARGS&&... rule_args) {
|
||||
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.
|
||||
/// @param source the source information
|
||||
/// @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
|
||||
template <typename NAME>
|
||||
template <typename... RULE_ARGS>
|
||||
const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
|
||||
builtin::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
auto* directive = create<ast::DiagnosticDirective>(
|
||||
source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
||||
RULE_ARGS&&... rule_args) {
|
||||
auto* rule = DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...);
|
||||
auto* directive =
|
||||
create<ast::DiagnosticDirective>(source, ast::DiagnosticControl(severity, rule));
|
||||
AST().AddDiagnosticDirective(directive);
|
||||
return directive;
|
||||
}
|
||||
|
||||
/// Add a diagnostic directive to the module.
|
||||
/// @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
|
||||
template <typename NAME>
|
||||
template <typename... RULE_ARGS>
|
||||
const ast::DiagnosticDirective* DiagnosticDirective(builtin::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
auto* directive = create<ast::DiagnosticDirective>(
|
||||
source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
||||
RULE_ARGS&&... rule_args) {
|
||||
auto* rule = DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...);
|
||||
auto* directive =
|
||||
create<ast::DiagnosticDirective>(source_, ast::DiagnosticControl(severity, rule));
|
||||
AST().AddDiagnosticDirective(directive);
|
||||
return directive;
|
||||
}
|
||||
|
|
|
@ -3092,7 +3092,7 @@ Expect<builtin::DiagnosticSeverity> ParserImpl::expect_severity_control_name() {
|
|||
}
|
||||
|
||||
// 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() {
|
||||
return expect_paren_block("diagnostic control", [&]() -> Expect<ast::DiagnosticControl> {
|
||||
auto severity_control = expect_severity_control_name();
|
||||
|
@ -3104,7 +3104,7 @@ Expect<ast::DiagnosticControl> ParserImpl::expect_diagnostic_control() {
|
|||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
auto rule_name = expect_ident("diagnostic control");
|
||||
auto rule_name = expect_diagnostic_rule_name();
|
||||
if (rule_name.errored) {
|
||||
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*/) {
|
||||
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};
|
||||
}
|
||||
|
||||
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();
|
||||
if (t.IsIdentifier()) {
|
||||
synchronized_ = true;
|
||||
|
@ -3230,7 +3257,7 @@ Expect<const ast::Identifier*> ParserImpl::expect_ident(std::string_view use) {
|
|||
return Failure::kErrored;
|
||||
}
|
||||
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>
|
||||
|
|
|
@ -636,14 +636,17 @@ class ParserImpl {
|
|||
/// Parses a single attribute, reporting an error if the next token does not
|
||||
/// represent a attribute.
|
||||
/// @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();
|
||||
/// 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();
|
||||
/// 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();
|
||||
/// 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.
|
||||
/// @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.
|
||||
/// Consumes the next token on match.
|
||||
/// @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.
|
||||
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
|
||||
/// the token `end`. `body` is called to parse the lexical block body
|
||||
/// between the `start` and `end` tokens. If the `start` or `end` tokens
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace tint::reader::wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, DiagnosticAttribute_Valid) {
|
||||
TEST_F(ParserImplTest, DiagnosticAttribute_Name) {
|
||||
auto p = parser("diagnostic(off, foo)");
|
||||
auto a = p->attribute();
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
|
@ -30,7 +30,22 @@ TEST_F(ParserImplTest, DiagnosticAttribute_Valid) {
|
|||
EXPECT_EQ(d->control.severity, builtin::DiagnosticSeverity::kOff);
|
||||
auto* r = d->control.rule_name;
|
||||
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
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace {
|
|||
using SeverityPair = std::pair<std::string, builtin::DiagnosticSeverity>;
|
||||
class DiagnosticControlParserTest : public ParserImplTestWithParam<SeverityPair> {};
|
||||
|
||||
TEST_P(DiagnosticControlParserTest, DiagnosticControl_Valid) {
|
||||
TEST_P(DiagnosticControlParserTest, DiagnosticControl_Name) {
|
||||
auto& params = GetParam();
|
||||
auto p = parser("(" + params.first + ", foo)");
|
||||
auto e = p->expect_diagnostic_control();
|
||||
|
@ -33,7 +33,21 @@ TEST_P(DiagnosticControlParserTest, DiagnosticControl_Valid) {
|
|||
|
||||
auto* r = e->rule_name;
|
||||
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,
|
||||
DiagnosticControlParserTest,
|
||||
|
@ -43,7 +57,7 @@ INSTANTIATE_TEST_SUITE_P(DiagnosticControlParserTest,
|
|||
SeverityPair{"info", builtin::DiagnosticSeverity::kInfo},
|
||||
SeverityPair{"off", builtin::DiagnosticSeverity::kOff}));
|
||||
|
||||
TEST_F(ParserImplTest, DiagnosticControl_Valid_TrailingComma) {
|
||||
TEST_F(ParserImplTest, DiagnosticControl_Name_TrailingComma) {
|
||||
auto p = parser("(error, foo,)");
|
||||
auto e = p->expect_diagnostic_control();
|
||||
EXPECT_FALSE(e.errored);
|
||||
|
@ -52,7 +66,21 @@ TEST_F(ParserImplTest, DiagnosticControl_Valid_TrailingComma) {
|
|||
|
||||
auto* r = e->rule_name;
|
||||
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) {
|
||||
|
@ -102,7 +130,15 @@ TEST_F(ParserImplTest, DiagnosticControl_MissingRuleName) {
|
|||
auto e = p->expect_diagnostic_control();
|
||||
EXPECT_TRUE(e.errored);
|
||||
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) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
namespace tint::reader::wgsl {
|
||||
namespace {
|
||||
|
||||
TEST_F(ParserImplTest, DiagnosticDirective_Valid) {
|
||||
TEST_F(ParserImplTest, DiagnosticDirective_Name) {
|
||||
auto p = parser("diagnostic(off, foo);");
|
||||
p->diagnostic_directive();
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
|
@ -33,7 +33,25 @@ TEST_F(ParserImplTest, DiagnosticDirective_Valid) {
|
|||
|
||||
auto* r = directive->control.rule_name;
|
||||
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) {
|
||||
|
|
|
@ -101,7 +101,7 @@ static utils::Vector<const ast::Attribute*, 2> createAttributes(const Source& so
|
|||
return {builder.Builtin(source, builtin::BuiltinValue::kPosition)};
|
||||
case AttributeKind::kDiagnostic:
|
||||
return {builder.DiagnosticAttribute(source, builtin::DiagnosticSeverity::kInfo,
|
||||
"chromium_unreachable_code")};
|
||||
"chromium", "unreachable_code")};
|
||||
case AttributeKind::kGroup:
|
||||
return {builder.Group(source, 1_a)};
|
||||
case AttributeKind::kId:
|
||||
|
|
|
@ -32,7 +32,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_DefaultSeverity) {
|
|||
}
|
||||
|
||||
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()};
|
||||
Func("foo", {}, ty.void_(), stmts);
|
||||
|
@ -42,7 +42,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective) {
|
|||
}
|
||||
|
||||
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()};
|
||||
Func("foo", {}, ty.void_(), stmts);
|
||||
|
@ -52,7 +52,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaDirective) {
|
|||
}
|
||||
|
||||
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()};
|
||||
Func("foo", {}, ty.void_(), stmts);
|
||||
|
@ -62,7 +62,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaDirective) {
|
|||
}
|
||||
|
||||
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()};
|
||||
Func("foo", {}, ty.void_(), stmts);
|
||||
|
@ -73,7 +73,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaDirective) {
|
|||
|
||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaAttribute) {
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||
|
||||
auto stmts = utils::Vector{Return(), Return()};
|
||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||
|
@ -84,7 +84,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaAttribute) {
|
|||
|
||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaAttribute) {
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium", "unreachable_code");
|
||||
|
||||
auto stmts = utils::Vector{Return(), Return()};
|
||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||
|
@ -95,7 +95,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_WarningViaAttribute) {
|
|||
|
||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaAttribute) {
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium", "unreachable_code");
|
||||
|
||||
auto stmts = utils::Vector{Return(), Return()};
|
||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||
|
@ -106,7 +106,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_InfoViaAttribute) {
|
|||
|
||||
TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaAttribute) {
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_code");
|
||||
|
||||
auto stmts = utils::Vector{Return(), Return()};
|
||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||
|
@ -116,15 +116,15 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_OffViaAttribute) {
|
|||
}
|
||||
|
||||
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; // Should produce a warning
|
||||
// }
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kWarning, "chromium", "unreachable_code");
|
||||
|
||||
auto stmts = utils::Vector{Return(), Return()};
|
||||
Func("foo", {}, ty.void_(), stmts, utils::Vector{attr});
|
||||
|
@ -134,7 +134,7 @@ TEST_F(ResolverDiagnosticControlTest, UnreachableCode_ErrorViaDirective_Overridd
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
||||
// @diagnostic(off, chromium_unreachable_code) fn foo() {
|
||||
// @diagnostic(off, chromium.unreachable_code) fn foo() {
|
||||
// return;
|
||||
// return; // Should not produce a diagnostic
|
||||
// }
|
||||
|
@ -144,13 +144,13 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
|||
// return; // Should produce a warning (default severity)
|
||||
// }
|
||||
//
|
||||
// @diagnostic(info, chromium_unreachable_code) fn bar() {
|
||||
// @diagnostic(info, chromium.unreachable_code) fn bar() {
|
||||
// return;
|
||||
// return; // Should produce an info
|
||||
// }
|
||||
{
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_code");
|
||||
Func("foo", {}, ty.void_(),
|
||||
utils::Vector{
|
||||
Return(),
|
||||
|
@ -167,7 +167,7 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
|||
}
|
||||
{
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kInfo, "chromium", "unreachable_code");
|
||||
Func("zoo", {}, ty.void_(),
|
||||
utils::Vector{
|
||||
Return(),
|
||||
|
@ -182,17 +182,17 @@ TEST_F(ResolverDiagnosticControlTest, FunctionAttributeScope) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
||||
// fn foo() @diagnostic(off, chromium_unreachable_code) {
|
||||
// fn foo() @diagnostic(off, chromium.unreachable_code) {
|
||||
// {
|
||||
// return;
|
||||
// return; // Should not produce a diagnostic
|
||||
// }
|
||||
// @diagnostic(warning, chromium_unreachable_code) {
|
||||
// if (true) @diagnostic(info, chromium_unreachable_code) {
|
||||
// @diagnostic(warning, chromium.unreachable_code) {
|
||||
// if (true) @diagnostic(info, chromium.unreachable_code) {
|
||||
// return;
|
||||
// return; // Should produce an info
|
||||
// } else {
|
||||
// while (true) @diagnostic(off, chromium_unreachable_code) {
|
||||
// while (true) @diagnostic(off, chromium.unreachable_code) {
|
||||
// return;
|
||||
// return; // Should not produce a diagnostic
|
||||
// }
|
||||
|
@ -203,7 +203,7 @@ TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
|||
// }
|
||||
|
||||
auto attr = [&](auto severity) {
|
||||
return utils::Vector{DiagnosticAttribute(severity, "chromium_unreachable_code")};
|
||||
return utils::Vector{DiagnosticAttribute(severity, "chromium", "unreachable_code")};
|
||||
};
|
||||
Func("foo", {}, ty.void_(),
|
||||
utils::Vector{
|
||||
|
@ -241,113 +241,157 @@ TEST_F(ResolverDiagnosticControlTest, BlockAttributeScope) {
|
|||
78:87 warning: code is unreachable)");
|
||||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Directive) {
|
||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedCoreRuleName_Directive) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_cod"));
|
||||
DiagnosticRuleName(Source{{12, 34}}, "derivative_uniform"));
|
||||
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', 'derivative_uniformity')");
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'derivative_uniform'
|
||||
Did you mean 'derivative_uniformity'?
|
||||
Possible values: 'derivative_uniformity')");
|
||||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedRuleName_Attribute) {
|
||||
TEST_F(ResolverDiagnosticControlTest, UnrecognizedCoreRuleName_Attribute) {
|
||||
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});
|
||||
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', 'derivative_uniformity')");
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'derivative_uniform'
|
||||
Did you mean '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) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
||||
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
||||
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Directive) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
||||
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
||||
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
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) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_codes"));
|
||||
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_codes"));
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_codes"));
|
||||
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_codes"));
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
56:78 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||
Did you mean 'chromium.unreachable_code'?
|
||||
Possible values: 'chromium.unreachable_code'
|
||||
56:78 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||
Did you mean 'chromium.unreachable_code'?
|
||||
Possible values: 'chromium.unreachable_code'
|
||||
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) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_codes");
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_codex");
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_codes");
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_codex");
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Attribute) {
|
||||
auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
||||
auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
||||
auto* attr1 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||
auto* attr2 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Attribute) {
|
||||
auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
||||
auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
||||
auto* attr1 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_code"));
|
||||
auto* attr2 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
||||
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_code"));
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
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) {
|
||||
auto* attr1 = DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_codes"));
|
||||
auto* attr2 = DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_codes"));
|
||||
auto* attr1 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError,
|
||||
DiagnosticRuleName(Source{{12, 34}}, "chromium", "unreachable_codes"));
|
||||
auto* attr2 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff,
|
||||
DiagnosticRuleName(Source{{56, 78}}, "chromium", "unreachable_codes"));
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
56:78 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||
Did you mean 'chromium.unreachable_code'?
|
||||
Possible values: 'chromium.unreachable_code'
|
||||
56:78 warning: unrecognized diagnostic rule 'chromium.unreachable_codes'
|
||||
Did you mean 'chromium.unreachable_code'?
|
||||
Possible values: 'chromium.unreachable_code'
|
||||
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) {
|
||||
auto* attr1 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium_unreachable_codes");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_codes");
|
||||
auto* attr2 =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium_unreachable_codex");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kOff, "chromium", "unreachable_codex");
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
|
|
@ -3466,15 +3466,33 @@ bool Resolver::InternalAttribute(const ast::InternalAttribute* attr) {
|
|||
|
||||
bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
|
||||
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();
|
||||
auto rule = builtin::ParseDiagnosticRule(rule_name);
|
||||
if (rule != builtin::DiagnosticRule::kUndefined) {
|
||||
if (control.rule_name->category) {
|
||||
Mark(control.rule_name->category);
|
||||
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);
|
||||
} else {
|
||||
utils::StringStream ss;
|
||||
ss << "unrecognized diagnostic rule '" << rule_name << "'\n";
|
||||
utils::SuggestAlternatives(rule_name, builtin::kDiagnosticRuleStrings, ss);
|
||||
ss << "unrecognized diagnostic rule '" << name << "'\n";
|
||||
utils::SuggestAlternatives(name, builtin::kCoreDiagnosticRuleStrings, ss);
|
||||
AddWarning(ss.str(), control.rule_name->source);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1563,7 +1563,7 @@ class UniformityGraph {
|
|||
builtin->Type() == builtin::Function::kTextureSampleCompare) {
|
||||
// Get the severity of derivative uniformity violations in this context.
|
||||
auto severity = sem_.DiagnosticSeverity(
|
||||
call, builtin::DiagnosticRule::kDerivativeUniformity);
|
||||
call, builtin::CoreDiagnosticRule::kDerivativeUniformity);
|
||||
if (severity != builtin::DiagnosticSeverity::kOff) {
|
||||
callsite_tag = {CallSiteTag::CallSiteRequiredToBeUniform, severity};
|
||||
}
|
||||
|
|
|
@ -159,9 +159,9 @@ Validator::Validator(
|
|||
atomic_composite_info_(atomic_composite_info),
|
||||
valid_type_storage_layouts_(valid_type_storage_layouts) {
|
||||
// Set default severities for filterable diagnostic rules.
|
||||
diagnostic_filters_.Set(builtin::DiagnosticRule::kDerivativeUniformity,
|
||||
diagnostic_filters_.Set(builtin::CoreDiagnosticRule::kDerivativeUniformity,
|
||||
builtin::DiagnosticSeverity::kError);
|
||||
diagnostic_filters_.Set(builtin::DiagnosticRule::kChromiumUnreachableCode,
|
||||
diagnostic_filters_.Set(builtin::ChromiumDiagnosticRule::kUnreachableCode,
|
||||
builtin::DiagnosticSeverity::kWarning);
|
||||
}
|
||||
|
||||
|
@ -1417,7 +1417,7 @@ bool Validator::EvaluationStage(const sem::ValueExpression* expr,
|
|||
bool Validator::Statements(utils::VectorRef<const ast::Statement*> stmts) const {
|
||||
for (auto* stmt : stmts) {
|
||||
if (!sem_.Get(stmt)->IsReachable()) {
|
||||
if (!AddDiagnostic(builtin::DiagnosticRule::kChromiumUnreachableCode,
|
||||
if (!AddDiagnostic(builtin::ChromiumDiagnosticRule::kUnreachableCode,
|
||||
"code is unreachable", stmt->source)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2530,9 +2530,12 @@ bool Validator::DiagnosticControls(utils::VectorRef<const ast::DiagnosticControl
|
|||
const char* use) const {
|
||||
// Make sure that no two diagnostic controls conflict.
|
||||
// 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) {
|
||||
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) {
|
||||
{
|
||||
utils::StringStream ss;
|
||||
|
@ -2541,8 +2544,8 @@ bool Validator::DiagnosticControls(utils::VectorRef<const ast::DiagnosticControl
|
|||
}
|
||||
{
|
||||
utils::StringStream ss;
|
||||
ss << "severity of '" << dc->rule_name->symbol.Name() << "' set to '"
|
||||
<< dc->severity << "' here";
|
||||
ss << "severity of '" << dc->rule_name->String() << "' set to '" << dc->severity
|
||||
<< "' here";
|
||||
AddNote(ss.str(), (*diag_added.value)->rule_name->source);
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -23,27 +23,27 @@ namespace {
|
|||
|
||||
class DiagnosticSeverityTest : public TestHelper {
|
||||
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
|
||||
/// 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) {
|
||||
// @diagnostic(off, chromium_unreachable_code)
|
||||
// @diagnostic(off, chromium.unreachable_code)
|
||||
// fn foo() {
|
||||
// @diagnostic(info, chromium_unreachable_code) {
|
||||
// @diagnostic(error, chromium_unreachable_code)
|
||||
// if (true) @diagnostic(warning, chromium_unreachable_code) {
|
||||
// @diagnostic(info, chromium.unreachable_code) {
|
||||
// @diagnostic(error, chromium.unreachable_code)
|
||||
// if (true) @diagnostic(warning, chromium.unreachable_code) {
|
||||
// return;
|
||||
// } else if (false) {
|
||||
// return;
|
||||
// } else @diagnostic(info, chromium_unreachable_code) {
|
||||
// } else @diagnostic(info, chromium.unreachable_code) {
|
||||
// return;
|
||||
// }
|
||||
// return;
|
||||
//
|
||||
// @diagnostic(error, chromium_unreachable_code)
|
||||
// switch (42) @diagnostic(off, chromium_unreachable_code) {
|
||||
// case 0 @diagnostic(warning, chromium_unreachable_code) {
|
||||
// @diagnostic(error, chromium.unreachable_code)
|
||||
// switch (42) @diagnostic(off, chromium.unreachable_code) {
|
||||
// case 0 @diagnostic(warning, chromium.unreachable_code) {
|
||||
// return;
|
||||
// }
|
||||
// default {
|
||||
|
@ -51,21 +51,21 @@ class DiagnosticSeverityTest : public TestHelper {
|
|||
// }
|
||||
// }
|
||||
//
|
||||
// @diagnostic(error, chromium_unreachable_code)
|
||||
// for (var i = 0; false; i++) @diagnostic(warning, chromium_unreachable_code) {
|
||||
// @diagnostic(error, chromium.unreachable_code)
|
||||
// for (var i = 0; false; i++) @diagnostic(warning, chromium.unreachable_code) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// @diagnostic(warning, chromium_unreachable_code)
|
||||
// loop @diagnostic(off, chromium_unreachable_code) {
|
||||
// @diagnostic(warning, chromium.unreachable_code)
|
||||
// loop @diagnostic(off, chromium.unreachable_code) {
|
||||
// return;
|
||||
// continuing @diagnostic(info, chromium_unreachable_code) {
|
||||
// continuing @diagnostic(info, chromium.unreachable_code) {
|
||||
// break if true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @diagnostic(error, chromium_unreachable_code)
|
||||
// while (false) @diagnostic(warning, chromium_unreachable_code) {
|
||||
// @diagnostic(error, chromium.unreachable_code)
|
||||
// while (false) @diagnostic(warning, chromium.unreachable_code) {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
@ -74,7 +74,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
|||
// fn bar() {
|
||||
// return;
|
||||
// }
|
||||
auto rule = builtin::DiagnosticRule::kChromiumUnreachableCode;
|
||||
auto rule = builtin::ChromiumDiagnosticRule::kUnreachableCode;
|
||||
auto func_severity = builtin::DiagnosticSeverity::kOff;
|
||||
auto block_severity = builtin::DiagnosticSeverity::kInfo;
|
||||
auto if_severity = builtin::DiagnosticSeverity::kError;
|
||||
|
@ -91,7 +91,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
|||
auto while_severity = builtin::DiagnosticSeverity::kError;
|
||||
auto while_body_severity = builtin::DiagnosticSeverity::kWarning;
|
||||
auto attr = [&](auto severity) {
|
||||
return utils::Vector{DiagnosticAttribute(severity, "chromium_unreachable_code")};
|
||||
return utils::Vector{DiagnosticAttribute(severity, "chromium", "unreachable_code")};
|
||||
};
|
||||
|
||||
auto* return_foo_if = Return();
|
||||
|
@ -123,7 +123,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
|||
attr(while_severity));
|
||||
auto* block_1 =
|
||||
Block(utils::Vector{if_foo, return_foo_block, swtch, fl, l, wl}, attr(block_severity));
|
||||
auto* func_attr = DiagnosticAttribute(func_severity, "chromium_unreachable_code");
|
||||
auto* func_attr = DiagnosticAttribute(func_severity, "chromium", "unreachable_code");
|
||||
auto* foo = Func("foo", {}, ty.void_(), utils::Vector{block_1}, utils::Vector{func_attr});
|
||||
|
||||
auto* return_bar = Return();
|
||||
|
@ -173,7 +173,7 @@ class DiagnosticSeverityTest : public TestHelper {
|
|||
};
|
||||
|
||||
TEST_F(DiagnosticSeverityTest, WithDirective) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||
Run(builtin::DiagnosticSeverity::kError);
|
||||
}
|
||||
|
||||
|
|
|
@ -1289,10 +1289,16 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
|
|||
}
|
||||
},
|
||||
[&](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) {
|
||||
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) {
|
||||
Switch(
|
||||
|
|
|
@ -192,9 +192,9 @@ fn tint_symbol() {
|
|||
EXPECT_THAT(data->remappings, ContainerEq(expected_remappings));
|
||||
}
|
||||
|
||||
TEST_F(RenamerTest, PreserveDiagnosticControls) {
|
||||
TEST_F(RenamerTest, PreserveCoreDiagnosticRuleName) {
|
||||
auto* src = R"(
|
||||
diagnostic(off, unreachable_code);
|
||||
diagnostic(off, chromium.unreachable_code);
|
||||
|
||||
@diagnostic(off, derivative_uniformity)
|
||||
@fragment
|
||||
|
@ -208,7 +208,7 @@ fn entry(@location(0) value : f32) -> @location(0) f32 {
|
|||
)";
|
||||
|
||||
auto* expect = R"(
|
||||
diagnostic(off, unreachable_code);
|
||||
diagnostic(off, chromium.unreachable_code);
|
||||
|
||||
@diagnostic(off, derivative_uniformity) @fragment
|
||||
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>
|
||||
struct Hasher<std::variant<TYPES...>> {
|
||||
/// @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,
|
||||
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,
|
||||
// suggest that. Don't bother with suggestions if the string was extremely long.
|
||||
constexpr size_t kSuggestionDistance = 5;
|
||||
|
@ -66,7 +67,7 @@ void SuggestAlternatives(std::string_view got,
|
|||
}
|
||||
}
|
||||
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]) {
|
||||
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 strings the list of possible values
|
||||
/// @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,
|
||||
Slice<char const* const> strings,
|
||||
utils::StringStream& ss);
|
||||
utils::StringStream& ss,
|
||||
std::string_view prefix = "");
|
||||
|
||||
} // namespace tint::utils
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ void GeneratorImpl::Generate() {
|
|||
|
||||
void GeneratorImpl::EmitDiagnosticControl(const ast::DiagnosticControl& diagnostic) {
|
||||
line() << "DiagnosticControl [severity: " << diagnostic.severity
|
||||
<< ", rule: " << diagnostic.rule_name->symbol.Name() << "]";
|
||||
<< ", rule: " << diagnostic.rule_name->String() << "]";
|
||||
}
|
||||
|
||||
void GeneratorImpl::EmitEnable(const ast::Enable* enable) {
|
||||
|
|
|
@ -82,8 +82,7 @@ void GeneratorImpl::Generate() {
|
|||
|
||||
void GeneratorImpl::EmitDiagnosticControl(utils::StringStream& out,
|
||||
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) {
|
||||
|
|
|
@ -22,25 +22,25 @@ namespace {
|
|||
using WgslGeneratorImplTest = TestHelper;
|
||||
|
||||
TEST_F(WgslGeneratorImplTest, Emit_DiagnosticDirective) {
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
||||
DiagnosticDirective(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
gen.Generate();
|
||||
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) {
|
||||
auto* attr =
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium_unreachable_code");
|
||||
DiagnosticAttribute(builtin::DiagnosticSeverity::kError, "chromium", "unreachable_code");
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
gen.Generate();
|
||||
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() {
|
||||
}
|
||||
)");
|
||||
|
|
Loading…
Reference in New Issue