tint/ast: Make DiagnosticControl a plain struct
Introduce DiagnosticDirective, which contains a DiagnosticControl struct (as does DiagnosticAttribute). Bug: tint:1809 Change-Id: I204001266ee472d2ee2827614a306acad53f12ba Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118060 Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: James Price <jrprice@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
parent
ededebbcf3
commit
98dc5a86cc
|
@ -264,6 +264,7 @@ libtint_source_set("libtint_syntax_tree_src") {
|
|||
"ast/depth_texture.h",
|
||||
"ast/diagnostic_attribute.h",
|
||||
"ast/diagnostic_control.h",
|
||||
"ast/diagnostic_directive.h",
|
||||
"ast/disable_validation_attribute.h",
|
||||
"ast/discard_statement.h",
|
||||
"ast/enable.h",
|
||||
|
@ -597,6 +598,8 @@ libtint_source_set("libtint_ast_src") {
|
|||
"ast/diagnostic_attribute.h",
|
||||
"ast/diagnostic_control.cc",
|
||||
"ast/diagnostic_control.h",
|
||||
"ast/diagnostic_directive.cc",
|
||||
"ast/diagnostic_directive.h",
|
||||
"ast/disable_validation_attribute.cc",
|
||||
"ast/disable_validation_attribute.h",
|
||||
"ast/discard_statement.cc",
|
||||
|
@ -1321,6 +1324,7 @@ if (tint_build_unittests) {
|
|||
"ast/continue_statement_test.cc",
|
||||
"ast/diagnostic_attribute_test.cc",
|
||||
"ast/diagnostic_control_test.cc",
|
||||
"ast/diagnostic_directive_test.cc",
|
||||
"ast/discard_statement_test.cc",
|
||||
"ast/enable_test.cc",
|
||||
"ast/extension_test.cc",
|
||||
|
|
|
@ -130,6 +130,8 @@ list(APPEND TINT_LIB_SRCS
|
|||
ast/diagnostic_attribute.h
|
||||
ast/diagnostic_control.cc
|
||||
ast/diagnostic_control.h
|
||||
ast/diagnostic_directive.cc
|
||||
ast/diagnostic_directive.h
|
||||
ast/disable_validation_attribute.cc
|
||||
ast/disable_validation_attribute.h
|
||||
ast/discard_statement.cc
|
||||
|
@ -843,6 +845,7 @@ if(TINT_BUILD_TESTS)
|
|||
ast/depth_texture_test.cc
|
||||
ast/diagnostic_attribute_test.cc
|
||||
ast/diagnostic_control_test.cc
|
||||
ast/diagnostic_directive_test.cc
|
||||
ast/discard_statement_test.cc
|
||||
ast/enable_test.cc
|
||||
ast/external_texture_test.cc
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "src/tint/ast/diagnostic_attribute.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
|
@ -25,8 +26,8 @@ namespace tint::ast {
|
|||
DiagnosticAttribute::DiagnosticAttribute(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
const ast::DiagnosticControl* dc)
|
||||
: Base(pid, nid, src), control(dc) {}
|
||||
ast::DiagnosticControl&& dc)
|
||||
: Base(pid, nid, src), control(std::move(dc)) {}
|
||||
|
||||
DiagnosticAttribute::~DiagnosticAttribute() = default;
|
||||
|
||||
|
@ -37,8 +38,9 @@ std::string DiagnosticAttribute::Name() const {
|
|||
const DiagnosticAttribute* DiagnosticAttribute::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source);
|
||||
auto dc = ctx->Clone(control);
|
||||
return ctx->dst->create<DiagnosticAttribute>(src, dc);
|
||||
auto rule = ctx->Clone(control.rule_name);
|
||||
DiagnosticControl dc(control.severity, rule);
|
||||
return ctx->dst->create<DiagnosticAttribute>(src, std::move(dc));
|
||||
}
|
||||
|
||||
} // namespace tint::ast
|
||||
|
|
|
@ -30,10 +30,7 @@ class DiagnosticAttribute final : public Castable<DiagnosticAttribute, Attribute
|
|||
/// @param nid the unique node identifier
|
||||
/// @param src the source of this node
|
||||
/// @param dc the diagnostic control
|
||||
DiagnosticAttribute(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
const ast::DiagnosticControl* dc);
|
||||
DiagnosticAttribute(ProgramID pid, NodeID nid, const Source& src, ast::DiagnosticControl&& dc);
|
||||
~DiagnosticAttribute() override;
|
||||
|
||||
/// @returns the WGSL name for the attribute
|
||||
|
@ -44,8 +41,8 @@ class DiagnosticAttribute final : public Castable<DiagnosticAttribute, Attribute
|
|||
/// @return the newly cloned node
|
||||
const DiagnosticAttribute* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The diagnostic control expression.
|
||||
const ast::DiagnosticControl* const control;
|
||||
/// The diagnostic control.
|
||||
const ast::DiagnosticControl control;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
|
|
@ -24,8 +24,8 @@ TEST_F(DiagnosticAttributeTest, Creation) {
|
|||
auto* name = Ident("foo");
|
||||
auto* d = DiagnosticAttribute(DiagnosticSeverity::kWarning, name);
|
||||
EXPECT_EQ(d->Name(), "diagnostic");
|
||||
EXPECT_EQ(d->control->severity, DiagnosticSeverity::kWarning);
|
||||
EXPECT_EQ(d->control->rule_name, name);
|
||||
EXPECT_EQ(d->control.severity, DiagnosticSeverity::kWarning);
|
||||
EXPECT_EQ(d->control.rule_name, name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -24,18 +24,13 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticControl);
|
||||
#include "src/tint/ast/identifier.h"
|
||||
#include "src/tint/ast/templated_identifier.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
DiagnosticControl::DiagnosticControl(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
DiagnosticSeverity sev,
|
||||
const Identifier* rule)
|
||||
: Base(pid, nid, src), severity(sev), rule_name(rule) {
|
||||
DiagnosticControl::DiagnosticControl(DiagnosticSeverity sev, const Identifier* rule)
|
||||
: severity(sev), rule_name(rule) {
|
||||
TINT_ASSERT(AST, rule != nullptr);
|
||||
if (rule) {
|
||||
// It is invalid for a diagnostic rule name to be templated
|
||||
|
@ -43,14 +38,6 @@ DiagnosticControl::DiagnosticControl(ProgramID pid,
|
|||
}
|
||||
}
|
||||
|
||||
DiagnosticControl::~DiagnosticControl() = default;
|
||||
|
||||
const DiagnosticControl* DiagnosticControl::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
auto rule = ctx->Clone(rule_name);
|
||||
return ctx->dst->create<DiagnosticControl>(src, severity, rule);
|
||||
}
|
||||
|
||||
diag::Severity ToSeverity(DiagnosticSeverity sc) {
|
||||
switch (sc) {
|
||||
case DiagnosticSeverity::kError:
|
||||
|
|
|
@ -14,18 +14,13 @@ See:
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticControl);
|
||||
#include "src/tint/ast/identifier.h"
|
||||
#include "src/tint/ast/templated_identifier.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
DiagnosticControl::DiagnosticControl(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
DiagnosticSeverity sev,
|
||||
const Identifier* rule)
|
||||
: Base(pid, nid, src), severity(sev), rule_name(rule) {
|
||||
DiagnosticControl::DiagnosticControl(DiagnosticSeverity sev, const Identifier* rule)
|
||||
: severity(sev), rule_name(rule) {
|
||||
TINT_ASSERT(AST, rule != nullptr);
|
||||
if (rule) {
|
||||
// It is invalid for a diagnostic rule name to be templated
|
||||
|
@ -33,14 +28,6 @@ DiagnosticControl::DiagnosticControl(ProgramID pid,
|
|||
}
|
||||
}
|
||||
|
||||
DiagnosticControl::~DiagnosticControl() = default;
|
||||
|
||||
const DiagnosticControl* DiagnosticControl::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
auto rule = ctx->Clone(rule_name);
|
||||
return ctx->dst->create<DiagnosticControl>(src, severity, rule);
|
||||
}
|
||||
|
||||
diag::Severity ToSeverity(DiagnosticSeverity sc) {
|
||||
switch (sc) {
|
||||
case DiagnosticSeverity::kError:
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/tint/ast/node.h"
|
||||
#include "src/tint/diagnostic/diagnostic.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
|
@ -91,26 +91,15 @@ diag::Severity ToSeverity(DiagnosticSeverity sc);
|
|||
using DiagnosticRuleSeverities = std::unordered_map<DiagnosticRule, DiagnosticSeverity>;
|
||||
|
||||
/// A diagnostic control used for diagnostic directives and attributes.
|
||||
class DiagnosticControl : public Castable<DiagnosticControl, Node> {
|
||||
struct DiagnosticControl {
|
||||
public:
|
||||
/// Default constructor.
|
||||
DiagnosticControl() {}
|
||||
|
||||
/// 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 sev the diagnostic severity
|
||||
/// @param rule the diagnostic rule name
|
||||
DiagnosticControl(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
DiagnosticSeverity sev,
|
||||
const Identifier* rule);
|
||||
|
||||
~DiagnosticControl() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const DiagnosticControl* Clone(CloneContext* ctx) const override;
|
||||
DiagnosticControl(DiagnosticSeverity sev, const Identifier* rule);
|
||||
|
||||
/// The diagnostic severity control.
|
||||
DiagnosticSeverity severity;
|
||||
|
|
|
@ -17,7 +17,7 @@ See:
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/tint/ast/node.h"
|
||||
#include "src/tint/diagnostic/diagnostic.h"
|
||||
|
||||
// Forward declarations
|
||||
namespace tint::ast {
|
||||
|
@ -39,26 +39,15 @@ diag::Severity ToSeverity(DiagnosticSeverity sc);
|
|||
using DiagnosticRuleSeverities = std::unordered_map<DiagnosticRule, DiagnosticSeverity>;
|
||||
|
||||
/// A diagnostic control used for diagnostic directives and attributes.
|
||||
class DiagnosticControl : public Castable<DiagnosticControl, Node> {
|
||||
struct DiagnosticControl {
|
||||
public:
|
||||
/// Default constructor.
|
||||
DiagnosticControl() {}
|
||||
|
||||
/// 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 sev the diagnostic severity
|
||||
/// @param rule the diagnostic rule name
|
||||
DiagnosticControl(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
DiagnosticSeverity sev,
|
||||
const Identifier* rule);
|
||||
|
||||
~DiagnosticControl() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const DiagnosticControl* Clone(CloneContext* ctx) const override;
|
||||
DiagnosticControl(DiagnosticSeverity sev, const Identifier* rule);
|
||||
|
||||
/// The diagnostic severity control.
|
||||
DiagnosticSeverity severity;
|
||||
|
|
|
@ -31,26 +31,12 @@ namespace {
|
|||
|
||||
using DiagnosticControlTest = TestHelper;
|
||||
|
||||
TEST_F(DiagnosticControlTest, Creation) {
|
||||
auto* name = Ident("foo");
|
||||
Source source;
|
||||
source.range.begin = Source::Location{20, 2};
|
||||
source.range.end = Source::Location{20, 5};
|
||||
auto* control = create<ast::DiagnosticControl>(source, DiagnosticSeverity::kWarning, name);
|
||||
EXPECT_EQ(control->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(control->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(control->source.range.end.line, 20u);
|
||||
EXPECT_EQ(control->source.range.end.column, 5u);
|
||||
EXPECT_EQ(control->severity, DiagnosticSeverity::kWarning);
|
||||
EXPECT_EQ(control->rule_name, name);
|
||||
}
|
||||
|
||||
TEST_F(DiagnosticControlTest, Assert_RuleNotTemplated) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<ast::DiagnosticControl>(DiagnosticSeverity::kWarning,
|
||||
b.Ident("name", "a", "b", "c"));
|
||||
ast::DiagnosticControl control(DiagnosticSeverity::kWarning,
|
||||
b.Ident("name", "a", "b", "c"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
|
|
@ -21,26 +21,12 @@ namespace {
|
|||
|
||||
using DiagnosticControlTest = TestHelper;
|
||||
|
||||
TEST_F(DiagnosticControlTest, Creation) {
|
||||
auto* name = Ident("foo");
|
||||
Source source;
|
||||
source.range.begin = Source::Location{20, 2};
|
||||
source.range.end = Source::Location{20, 5};
|
||||
auto* control = create<ast::DiagnosticControl>(source, DiagnosticSeverity::kWarning, name);
|
||||
EXPECT_EQ(control->source.range.begin.line, 20u);
|
||||
EXPECT_EQ(control->source.range.begin.column, 2u);
|
||||
EXPECT_EQ(control->source.range.end.line, 20u);
|
||||
EXPECT_EQ(control->source.range.end.column, 5u);
|
||||
EXPECT_EQ(control->severity, DiagnosticSeverity::kWarning);
|
||||
EXPECT_EQ(control->rule_name, name);
|
||||
}
|
||||
|
||||
TEST_F(DiagnosticControlTest, Assert_RuleNotTemplated) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.create<ast::DiagnosticControl>(DiagnosticSeverity::kWarning,
|
||||
b.Ident("name", "a", "b", "c"));
|
||||
ast::DiagnosticControl control(DiagnosticSeverity::kWarning,
|
||||
b.Ident("name", "a", "b", "c"));
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// 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_directive.h"
|
||||
|
||||
#include "src/tint/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::DiagnosticDirective);
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
DiagnosticDirective::DiagnosticDirective(ProgramID pid,
|
||||
NodeID nid,
|
||||
const Source& src,
|
||||
DiagnosticControl&& dc)
|
||||
: Base(pid, nid, src), control(std::move(dc)) {}
|
||||
|
||||
DiagnosticDirective::DiagnosticDirective(DiagnosticDirective&&) = default;
|
||||
|
||||
DiagnosticDirective::~DiagnosticDirective() = default;
|
||||
|
||||
const DiagnosticDirective* DiagnosticDirective::Clone(CloneContext* ctx) const {
|
||||
auto src = ctx->Clone(source);
|
||||
auto rule = ctx->Clone(control.rule_name);
|
||||
DiagnosticControl dc(control.severity, rule);
|
||||
return ctx->dst->create<DiagnosticDirective>(src, std::move(dc));
|
||||
}
|
||||
} // namespace tint::ast
|
|
@ -0,0 +1,58 @@
|
|||
// 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_DIRECTIVE_H_
|
||||
#define SRC_TINT_AST_DIAGNOSTIC_DIRECTIVE_H_
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "src/tint/ast/diagnostic_control.h"
|
||||
#include "src/tint/ast/node.h"
|
||||
|
||||
namespace tint::ast {
|
||||
|
||||
/// A "diagnostic" directive. Example:
|
||||
/// ```
|
||||
/// // Turn off diagnostics for derivative uniformity violations.
|
||||
/// diagnostic(off, derivative_uniformity);
|
||||
/// ```
|
||||
class DiagnosticDirective final : public Castable<DiagnosticDirective, Node> {
|
||||
public:
|
||||
/// Create a extension
|
||||
/// @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 dc the diagnostic control
|
||||
DiagnosticDirective(ProgramID pid, NodeID nid, const Source& src, DiagnosticControl&& dc);
|
||||
|
||||
/// Move constructor
|
||||
DiagnosticDirective(DiagnosticDirective&&);
|
||||
|
||||
/// Destructor
|
||||
~DiagnosticDirective() override;
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext` `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
const DiagnosticDirective* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// The diagnostic control.
|
||||
const DiagnosticControl control;
|
||||
};
|
||||
|
||||
} // namespace tint::ast
|
||||
|
||||
#endif // SRC_TINT_AST_DIAGNOSTIC_DIRECTIVE_H_
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2022 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_directive.h"
|
||||
|
||||
#include "src/tint/ast/test_helper.h"
|
||||
|
||||
namespace tint::ast {
|
||||
namespace {
|
||||
|
||||
using DiagnosticDirectiveTest = TestHelper;
|
||||
|
||||
TEST_F(DiagnosticDirectiveTest, Creation) {
|
||||
auto* name = Ident("foo");
|
||||
DiagnosticControl control(ast::DiagnosticSeverity::kWarning, name);
|
||||
auto* diag = create<ast::DiagnosticDirective>(Source{{{10, 5}, {10, 15}}}, std::move(control));
|
||||
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, ast::DiagnosticSeverity::kWarning);
|
||||
EXPECT_EQ(diag->control.rule_name, name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::ast
|
|
@ -71,9 +71,9 @@ void Module::BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags
|
|||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
|
||||
global_variables_.Push(var);
|
||||
},
|
||||
[&](const DiagnosticControl* diag_control) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, diag_control, program_id);
|
||||
diagnostic_controls_.Push(diag_control);
|
||||
[&](const DiagnosticDirective* diagnostic) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, diagnostic, program_id);
|
||||
diagnostic_directives_.Push(diagnostic);
|
||||
},
|
||||
[&](const Enable* enable) {
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, enable, program_id);
|
||||
|
@ -86,11 +86,11 @@ void Module::BinGlobalDeclaration(const tint::ast::Node* decl, diag::List& diags
|
|||
[&](Default) { TINT_ICE(AST, diags) << "Unknown global declaration type"; });
|
||||
}
|
||||
|
||||
void Module::AddDiagnosticControl(const ast::DiagnosticControl* control) {
|
||||
TINT_ASSERT(AST, control);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, control, program_id);
|
||||
global_declarations_.Push(control);
|
||||
diagnostic_controls_.Push(control);
|
||||
void Module::AddDiagnosticDirective(const ast::DiagnosticDirective* directive) {
|
||||
TINT_ASSERT(AST, directive);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, directive, program_id);
|
||||
global_declarations_.Push(directive);
|
||||
diagnostic_directives_.Push(directive);
|
||||
}
|
||||
|
||||
void Module::AddEnable(const ast::Enable* enable) {
|
||||
|
@ -143,6 +143,7 @@ void Module::Copy(CloneContext* ctx, const Module* src) {
|
|||
functions_.Clear();
|
||||
global_variables_.Clear();
|
||||
enables_.Clear();
|
||||
diagnostic_directives_.Clear();
|
||||
|
||||
for (auto* decl : global_declarations_) {
|
||||
if (TINT_UNLIKELY(!decl)) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "src/tint/ast/const_assert.h"
|
||||
#include "src/tint/ast/diagnostic_control.h"
|
||||
#include "src/tint/ast/diagnostic_directive.h"
|
||||
#include "src/tint/ast/enable.h"
|
||||
#include "src/tint/ast/function.h"
|
||||
#include "src/tint/ast/type.h"
|
||||
|
@ -93,16 +93,16 @@ class Module final : public Castable<Module, Node> {
|
|||
return out;
|
||||
}
|
||||
|
||||
/// Add a global diagnostic control to the module
|
||||
/// @param control the diagnostic control to add
|
||||
void AddDiagnosticControl(const DiagnosticControl* control);
|
||||
/// Add a diagnostic directive to the module
|
||||
/// @param diagnostic the diagnostic directive to add
|
||||
void AddDiagnosticDirective(const DiagnosticDirective* diagnostic);
|
||||
|
||||
/// Add a enable directive to the module
|
||||
/// @param ext the enable directive to add
|
||||
void AddEnable(const Enable* ext);
|
||||
|
||||
/// @returns the global diagnostic controls for the module
|
||||
const auto& DiagnosticControls() const { return diagnostic_controls_; }
|
||||
/// @returns the diagnostic directives for the module
|
||||
const auto& DiagnosticDirectives() const { return diagnostic_directives_; }
|
||||
|
||||
/// @returns the extension set for the module
|
||||
const auto& Enables() const { return enables_; }
|
||||
|
@ -154,7 +154,7 @@ class Module final : public Castable<Module, Node> {
|
|||
utils::Vector<const TypeDecl*, 16> type_decls_;
|
||||
FunctionList functions_;
|
||||
utils::Vector<const Variable*, 32> global_variables_;
|
||||
utils::Vector<const DiagnosticControl*, 8> diagnostic_controls_;
|
||||
utils::Vector<const DiagnosticDirective*, 8> diagnostic_directives_;
|
||||
utils::Vector<const Enable*, 8> enables_;
|
||||
utils::Vector<const ConstAssert*, 8> const_asserts_;
|
||||
};
|
||||
|
|
|
@ -149,10 +149,10 @@ TEST_F(ModuleTest, Directives) {
|
|||
enable_1,
|
||||
enable_2,
|
||||
}));
|
||||
EXPECT_THAT(program.AST().DiagnosticControls(), ::testing::ContainerEq(utils::Vector{
|
||||
diagnostic_1,
|
||||
diagnostic_2,
|
||||
}));
|
||||
EXPECT_THAT(program.AST().DiagnosticDirectives(), ::testing::ContainerEq(utils::Vector{
|
||||
diagnostic_1,
|
||||
diagnostic_2,
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "src/tint/ast/depth_texture.h"
|
||||
#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/disable_validation_attribute.h"
|
||||
#include "src/tint/ast/discard_statement.h"
|
||||
#include "src/tint/ast/enable.h"
|
||||
|
@ -3309,7 +3310,7 @@ class ProgramBuilder {
|
|||
static_assert(!traits::IsType<traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
|
||||
"it is invalid for a diagnostic rule name to be templated");
|
||||
return create<ast::DiagnosticAttribute>(
|
||||
source, DiagnosticControl(source, severity, std::forward<NAME>(rule_name)));
|
||||
source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
||||
}
|
||||
|
||||
/// Creates an ast::DiagnosticAttribute
|
||||
|
@ -3320,57 +3321,35 @@ class ProgramBuilder {
|
|||
const ast::DiagnosticAttribute* DiagnosticAttribute(ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
return create<ast::DiagnosticAttribute>(
|
||||
source_, DiagnosticControl(source_, severity, std::forward<NAME>(rule_name)));
|
||||
source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
||||
}
|
||||
|
||||
/// Creates an ast::DiagnosticControl
|
||||
/// 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
|
||||
/// @returns the diagnostic control pointer
|
||||
/// @returns the diagnostic directive pointer
|
||||
template <typename NAME>
|
||||
const ast::DiagnosticControl* DiagnosticControl(const Source& source,
|
||||
ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
return create<ast::DiagnosticControl>(source, severity,
|
||||
Ident(std::forward<NAME>(rule_name)));
|
||||
const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
|
||||
ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
auto* directive = create<ast::DiagnosticDirective>(
|
||||
source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
||||
AST().AddDiagnosticDirective(directive);
|
||||
return directive;
|
||||
}
|
||||
|
||||
/// Creates an ast::DiagnosticControl
|
||||
/// Add a diagnostic directive to the module.
|
||||
/// @param severity the diagnostic severity control
|
||||
/// @param rule_name the diagnostic rule name
|
||||
/// @returns the diagnostic control pointer
|
||||
/// @returns the diagnostic directive pointer
|
||||
template <typename NAME>
|
||||
const ast::DiagnosticControl* DiagnosticControl(ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
return create<ast::DiagnosticControl>(source_, severity,
|
||||
Ident(std::forward<NAME>(rule_name)));
|
||||
}
|
||||
|
||||
/// Add a global diagnostic control to the module.
|
||||
/// @param source the source information
|
||||
/// @param severity the diagnostic severity control
|
||||
/// @param rule_name the diagnostic rule name
|
||||
/// @returns the diagnostic control pointer
|
||||
template <typename NAME>
|
||||
const ast::DiagnosticControl* DiagnosticDirective(const Source& source,
|
||||
ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
auto* control = DiagnosticControl(source, severity, Ident(std::forward<NAME>(rule_name)));
|
||||
AST().AddDiagnosticControl(control);
|
||||
return control;
|
||||
}
|
||||
|
||||
/// Add a global diagnostic control to the module.
|
||||
/// @param severity the diagnostic severity control
|
||||
/// @param rule_name the diagnostic rule name
|
||||
/// @returns the diagnostic control pointer
|
||||
template <typename NAME>
|
||||
const ast::DiagnosticControl* DiagnosticDirective(ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
auto* control = DiagnosticControl(source_, severity, Ident(std::forward<NAME>(rule_name)));
|
||||
AST().AddDiagnosticControl(control);
|
||||
return control;
|
||||
const ast::DiagnosticDirective* DiagnosticDirective(ast::DiagnosticSeverity severity,
|
||||
NAME&& rule_name) {
|
||||
auto* directive = create<ast::DiagnosticDirective>(
|
||||
source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
|
||||
AST().AddDiagnosticDirective(directive);
|
||||
return directive;
|
||||
}
|
||||
|
||||
/// Sets the current builder source to `src`
|
||||
|
|
|
@ -383,6 +383,7 @@ Maybe<Void> ParserImpl::diagnostic_directive() {
|
|||
return Failure::kNoMatch;
|
||||
}
|
||||
|
||||
auto source = last_source();
|
||||
auto control = expect_diagnostic_control();
|
||||
if (control.errored) {
|
||||
return Failure::kErrored;
|
||||
|
@ -392,7 +393,8 @@ Maybe<Void> ParserImpl::diagnostic_directive() {
|
|||
return Failure::kErrored;
|
||||
}
|
||||
|
||||
builder_.AST().AddDiagnosticControl(std::move(control.value));
|
||||
auto* directive = create<ast::DiagnosticDirective>(source, std::move(control.value));
|
||||
builder_.AST().AddDiagnosticDirective(directive);
|
||||
|
||||
return kSuccess;
|
||||
});
|
||||
|
@ -3587,7 +3589,7 @@ Maybe<const ast::Attribute*> ParserImpl::attribute() {
|
|||
if (control.errored) {
|
||||
return Failure::kErrored;
|
||||
}
|
||||
return create<ast::DiagnosticAttribute>(t.source(), control.value);
|
||||
return create<ast::DiagnosticAttribute>(t.source(), std::move(control.value));
|
||||
}
|
||||
|
||||
if (t == "fragment") {
|
||||
|
@ -3756,9 +3758,8 @@ Expect<ast::DiagnosticSeverity> ParserImpl::expect_severity_control_name() {
|
|||
|
||||
// diagnostic_control
|
||||
// : PAREN_LEFT severity_control_name COMMA ident_pattern_token COMMA ? PAREN_RIGHT
|
||||
Expect<const ast::DiagnosticControl*> ParserImpl::expect_diagnostic_control() {
|
||||
auto source = last_source();
|
||||
return expect_paren_block("diagnostic control", [&]() -> Expect<const ast::DiagnosticControl*> {
|
||||
Expect<ast::DiagnosticControl> ParserImpl::expect_diagnostic_control() {
|
||||
return expect_paren_block("diagnostic control", [&]() -> Expect<ast::DiagnosticControl> {
|
||||
auto severity_control = expect_severity_control_name();
|
||||
if (severity_control.errored) {
|
||||
return Failure::kErrored;
|
||||
|
@ -3774,8 +3775,8 @@ Expect<const ast::DiagnosticControl*> ParserImpl::expect_diagnostic_control() {
|
|||
}
|
||||
match(Token::Type::kComma);
|
||||
|
||||
return create<ast::DiagnosticControl>(source, severity_control.value,
|
||||
builder_.Ident(rule_name.source, rule_name.value));
|
||||
return ast::DiagnosticControl(severity_control.value,
|
||||
builder_.Ident(rule_name.source, rule_name.value));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -717,7 +717,7 @@ class ParserImpl {
|
|||
Expect<ast::DiagnosticSeverity> expect_severity_control_name();
|
||||
/// Parses a diagnostic_control grammar element.
|
||||
/// @return the parsed diagnostic control, or nullptr on error.
|
||||
Expect<const ast::DiagnosticControl*> expect_diagnostic_control();
|
||||
Expect<ast::DiagnosticControl> expect_diagnostic_control();
|
||||
|
||||
/// Splits a peekable token into to parts filling in the peekable fields.
|
||||
/// @param lhs the token to set in the current position
|
||||
|
|
|
@ -26,8 +26,8 @@ TEST_F(ParserImplTest, DiagnosticAttribute_Valid) {
|
|||
EXPECT_TRUE(a.matched);
|
||||
auto* d = a.value->As<ast::DiagnosticAttribute>();
|
||||
ASSERT_NE(d, nullptr);
|
||||
EXPECT_EQ(d->control->severity, ast::DiagnosticSeverity::kOff);
|
||||
auto* r = d->control->rule_name;
|
||||
EXPECT_EQ(d->control.severity, ast::DiagnosticSeverity::kOff);
|
||||
auto* r = d->control.rule_name;
|
||||
ASSERT_NE(r, nullptr);
|
||||
EXPECT_EQ(p->builder().Symbols().NameFor(r->symbol), "foo");
|
||||
}
|
||||
|
|
|
@ -28,8 +28,6 @@ TEST_P(DiagnosticControlParserTest, DiagnosticControl_Valid) {
|
|||
auto e = p->expect_diagnostic_control();
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
ASSERT_TRUE(e->Is<ast::DiagnosticControl>());
|
||||
EXPECT_EQ(e->severity, params.second);
|
||||
|
||||
auto* r = e->rule_name;
|
||||
|
@ -48,8 +46,6 @@ TEST_F(ParserImplTest, DiagnosticControl_Valid_TrailingComma) {
|
|||
auto e = p->expect_diagnostic_control();
|
||||
EXPECT_FALSE(e.errored);
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e.value, nullptr);
|
||||
ASSERT_TRUE(e->Is<ast::DiagnosticControl>());
|
||||
EXPECT_EQ(e->severity, ast::DiagnosticSeverity::kError);
|
||||
|
||||
auto* r = e->rule_name;
|
||||
|
|
|
@ -24,13 +24,13 @@ TEST_F(ParserImplTest, DiagnosticDirective_Valid) {
|
|||
p->diagnostic_directive();
|
||||
EXPECT_FALSE(p->has_error()) << p->error();
|
||||
auto& ast = p->builder().AST();
|
||||
ASSERT_EQ(ast.DiagnosticControls().Length(), 1u);
|
||||
auto* control = ast.DiagnosticControls()[0];
|
||||
EXPECT_EQ(control->severity, ast::DiagnosticSeverity::kOff);
|
||||
ASSERT_EQ(ast.DiagnosticDirectives().Length(), 1u);
|
||||
auto* directive = ast.DiagnosticDirectives()[0];
|
||||
EXPECT_EQ(directive->control.severity, ast::DiagnosticSeverity::kOff);
|
||||
ASSERT_EQ(ast.GlobalDeclarations().Length(), 1u);
|
||||
EXPECT_EQ(ast.GlobalDeclarations()[0], control);
|
||||
EXPECT_EQ(ast.GlobalDeclarations()[0], directive);
|
||||
|
||||
auto* r = control->rule_name;
|
||||
auto* r = directive->control.rule_name;
|
||||
ASSERT_NE(r, nullptr);
|
||||
EXPECT_EQ(p->builder().Symbols().NameFor(r->symbol), "foo");
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ TEST_F(ParserImplTest, DiagnosticDirective_MissingSemicolon) {
|
|||
EXPECT_EQ(p->error(), "1:21: expected ';' for diagnostic directive");
|
||||
auto program = p->program();
|
||||
auto& ast = program.AST();
|
||||
EXPECT_EQ(ast.DiagnosticControls().Length(), 0u);
|
||||
EXPECT_EQ(ast.DiagnosticDirectives().Length(), 0u);
|
||||
EXPECT_EQ(ast.GlobalDeclarations().Length(), 0u);
|
||||
}
|
||||
|
||||
|
|
|
@ -207,8 +207,8 @@ class DependencyScanner {
|
|||
TraverseExpression(var->initializer);
|
||||
}
|
||||
},
|
||||
[&](const ast::DiagnosticControl*) {
|
||||
// Diagnostic control directives do not affect the dependency graph.
|
||||
[&](const ast::DiagnosticDirective*) {
|
||||
// Diagnostic directives do not affect the dependency graph.
|
||||
},
|
||||
[&](const ast::Enable*) {
|
||||
// Enable directives do not affect the dependency graph.
|
||||
|
@ -561,7 +561,7 @@ struct DependencyAnalysis {
|
|||
[&](const ast::TypeDecl* td) { return td->name; },
|
||||
[&](const ast::Function* func) { return func->symbol; },
|
||||
[&](const ast::Variable* var) { return var->symbol; },
|
||||
[&](const ast::DiagnosticControl*) { return Symbol(); },
|
||||
[&](const ast::DiagnosticDirective*) { return Symbol(); },
|
||||
[&](const ast::Enable*) { return Symbol(); },
|
||||
[&](const ast::ConstAssert*) { return Symbol(); },
|
||||
[&](Default) {
|
||||
|
@ -672,13 +672,13 @@ struct DependencyAnalysis {
|
|||
|
||||
// Make sure all directives go before any other global declarations.
|
||||
for (auto* global : declaration_order_) {
|
||||
if (global->node->IsAnyOf<ast::DiagnosticControl, ast::Enable>()) {
|
||||
if (global->node->IsAnyOf<ast::DiagnosticDirective, ast::Enable>()) {
|
||||
sorted_.Add(global->node);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto* global : declaration_order_) {
|
||||
if (global->node->IsAnyOf<ast::DiagnosticControl, ast::Enable>()) {
|
||||
if (global->node->IsAnyOf<ast::DiagnosticDirective, ast::Enable>()) {
|
||||
// Skip directives here, as they are already added.
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -1095,8 +1095,7 @@ TEST_F(ResolverDependencyGraphOrderedGlobalsTest, DirectiveFirst) {
|
|||
auto* var_1 = GlobalVar("SYMBOL1", ty.i32());
|
||||
auto* enable = Enable(ast::Extension::kF16);
|
||||
auto* var_2 = GlobalVar("SYMBOL2", ty.f32());
|
||||
auto* diagnostic = DiagnosticControl(ast::DiagnosticSeverity::kWarning, "foo");
|
||||
AST().AddDiagnosticControl(diagnostic);
|
||||
auto* diagnostic = DiagnosticDirective(ast::DiagnosticSeverity::kWarning, "foo");
|
||||
|
||||
EXPECT_THAT(AST().GlobalDeclarations(), ElementsAre(var_1, enable, var_2, diagnostic));
|
||||
EXPECT_THAT(Build().ordered_globals, ElementsAre(enable, diagnostic, var_1, var_2));
|
||||
|
|
|
@ -268,10 +268,10 @@ TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Directive) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Directive) {
|
||||
DiagnosticDirective(Source{{12, 34}}, ast::DiagnosticSeverity::kError,
|
||||
"chromium_unreachable_code");
|
||||
DiagnosticDirective(Source{{56, 78}}, ast::DiagnosticSeverity::kOff,
|
||||
"chromium_unreachable_code");
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(56:78 error: conflicting diagnostic directive
|
||||
|
@ -279,16 +279,16 @@ TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Directi
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameUnknownNameDifferentSeverity_Directive) {
|
||||
DiagnosticDirective(Source{{12, 34}}, ast::DiagnosticSeverity::kError,
|
||||
"chromium_unreachable_codes");
|
||||
DiagnosticDirective(Source{{56, 78}}, ast::DiagnosticSeverity::kOff,
|
||||
"chromium_unreachable_codes");
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_codes"));
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_codes"));
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
56:78 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
56:78 error: conflicting diagnostic directive
|
||||
|
@ -296,10 +296,8 @@ Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_DifferentUnknownNameDifferentSeverity_Directive) {
|
||||
DiagnosticDirective(Source{{12, 34}}, ast::DiagnosticSeverity::kError,
|
||||
"chromium_unreachable_codes");
|
||||
DiagnosticDirective(Source{{56, 78}}, ast::DiagnosticSeverity::kOff,
|
||||
"chromium_unreachable_codex");
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kError, "chromium_unreachable_codes");
|
||||
DiagnosticDirective(ast::DiagnosticSeverity::kOff, "chromium_unreachable_codex");
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
|
@ -313,10 +311,10 @@ TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameSameSeverity_Attribute) {
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Attribute) {
|
||||
auto* attr1 = DiagnosticAttribute(Source{{12, 34}}, ast::DiagnosticSeverity::kError,
|
||||
"chromium_unreachable_code");
|
||||
auto* attr2 = DiagnosticAttribute(Source{{56, 78}}, ast::DiagnosticSeverity::kOff,
|
||||
"chromium_unreachable_code");
|
||||
auto* attr1 = DiagnosticAttribute(ast::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_code"));
|
||||
auto* attr2 = DiagnosticAttribute(ast::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_code"));
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
|
@ -325,17 +323,17 @@ TEST_F(ResolverDiagnosticControlTest, Conflict_SameNameDifferentSeverity_Attribu
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_SameUnknownNameDifferentSeverity_Attribute) {
|
||||
auto* attr1 = DiagnosticAttribute(Source{{12, 34}}, ast::DiagnosticSeverity::kError,
|
||||
"chromium_unreachable_codes");
|
||||
auto* attr2 = DiagnosticAttribute(Source{{56, 78}}, ast::DiagnosticSeverity::kOff,
|
||||
"chromium_unreachable_codes");
|
||||
auto* attr1 = DiagnosticAttribute(ast::DiagnosticSeverity::kError,
|
||||
Ident(Source{{12, 34}}, "chromium_unreachable_codes"));
|
||||
auto* attr2 = DiagnosticAttribute(ast::DiagnosticSeverity::kOff,
|
||||
Ident(Source{{56, 78}}, "chromium_unreachable_codes"));
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
R"(12:34 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
56:78 warning: unrecognized diagnostic rule 'chromium_unreachable_codes'
|
||||
Did you mean 'chromium_unreachable_code'?
|
||||
Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
||||
56:78 error: conflicting diagnostic attribute
|
||||
|
@ -343,10 +341,9 @@ Possible values: 'chromium_unreachable_code', 'derivative_uniformity'
|
|||
}
|
||||
|
||||
TEST_F(ResolverDiagnosticControlTest, Conflict_DifferentUnknownNameDifferentSeverity_Attribute) {
|
||||
auto* attr1 = DiagnosticAttribute(Source{{12, 34}}, ast::DiagnosticSeverity::kError,
|
||||
"chromium_unreachable_codes");
|
||||
auto* attr2 = DiagnosticAttribute(Source{{56, 78}}, ast::DiagnosticSeverity::kOff,
|
||||
"chromium_unreachable_codex");
|
||||
auto* attr1 =
|
||||
DiagnosticAttribute(ast::DiagnosticSeverity::kError, "chromium_unreachable_codes");
|
||||
auto* attr2 = DiagnosticAttribute(ast::DiagnosticSeverity::kOff, "chromium_unreachable_codex");
|
||||
Func("foo", {}, ty.void_(), {}, utils::Vector{attr1, attr2});
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
|
|
@ -158,11 +158,15 @@ bool Resolver::ResolveInternal() {
|
|||
Mark(&builder_->AST());
|
||||
|
||||
// Process all module-scope declarations in dependency order.
|
||||
utils::Vector<const ast::DiagnosticControl*, 4> diagnostic_controls;
|
||||
for (auto* decl : dependencies_.ordered_globals) {
|
||||
Mark(decl);
|
||||
if (!Switch<bool>(
|
||||
decl, //
|
||||
[&](const ast::DiagnosticControl* dc) { return DiagnosticControl(dc); },
|
||||
[&](const ast::DiagnosticDirective* d) {
|
||||
diagnostic_controls.Push(&d->control);
|
||||
return DiagnosticControl(d->control);
|
||||
},
|
||||
[&](const ast::Enable* e) { return Enable(e); },
|
||||
[&](const ast::TypeDecl* td) { return TypeDecl(td); },
|
||||
[&](const ast::Function* func) { return Function(func); },
|
||||
|
@ -183,7 +187,7 @@ bool Resolver::ResolveInternal() {
|
|||
|
||||
SetShadows();
|
||||
|
||||
if (!validator_.DiagnosticControls(builder_->AST().DiagnosticControls(), "directive")) {
|
||||
if (!validator_.DiagnosticControls(diagnostic_controls, "directive")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -989,7 +993,6 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
|||
for (auto* attr : decl->attributes) {
|
||||
Mark(attr);
|
||||
if (auto* dc = attr->As<ast::DiagnosticAttribute>()) {
|
||||
Mark(dc->control);
|
||||
if (!DiagnosticControl(dc->control)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -3069,18 +3072,18 @@ sem::Expression* Resolver::UnaryOp(const ast::UnaryOpExpression* unary) {
|
|||
return sem;
|
||||
}
|
||||
|
||||
bool Resolver::DiagnosticControl(const ast::DiagnosticControl* control) {
|
||||
Mark(control->rule_name);
|
||||
bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
|
||||
Mark(control.rule_name);
|
||||
|
||||
auto rule_name = builder_->Symbols().NameFor(control->rule_name->symbol);
|
||||
auto rule_name = builder_->Symbols().NameFor(control.rule_name->symbol);
|
||||
auto rule = ast::ParseDiagnosticRule(rule_name);
|
||||
if (rule != ast::DiagnosticRule::kUndefined) {
|
||||
validator_.DiagnosticFilters().Set(rule, control->severity);
|
||||
validator_.DiagnosticFilters().Set(rule, control.severity);
|
||||
} else {
|
||||
std::ostringstream ss;
|
||||
ss << "unrecognized diagnostic rule '" << rule_name << "'\n";
|
||||
utils::SuggestAlternatives(rule_name, ast::kDiagnosticRuleStrings, ss);
|
||||
AddWarning(ss.str(), control->rule_name->source);
|
||||
AddWarning(ss.str(), control.rule_name->source);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -3863,7 +3866,6 @@ SEM* Resolver::StatementScope(const ast::Statement* ast, SEM* sem, F&& callback)
|
|||
for (auto* attr : stmt->attributes) {
|
||||
Mark(attr);
|
||||
if (auto* dc = attr->template As<ast::DiagnosticAttribute>()) {
|
||||
Mark(dc->control);
|
||||
if (!DiagnosticControl(dc->control)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -263,7 +263,7 @@ class Resolver {
|
|||
|
||||
/// @param control the diagnostic control
|
||||
/// @returns true on success, false on failure
|
||||
bool DiagnosticControl(const ast::DiagnosticControl* control);
|
||||
bool DiagnosticControl(const ast::DiagnosticControl& control);
|
||||
|
||||
/// @param enable the enable declaration
|
||||
/// @returns the resolved extension
|
||||
|
|
|
@ -2433,7 +2433,7 @@ bool Validator::NoDuplicateAttributes(utils::VectorRef<const ast::Attribute*> at
|
|||
for (auto* d : attributes) {
|
||||
if (auto* diag = d->As<ast::DiagnosticAttribute>()) {
|
||||
// Allow duplicate diagnostic attributes, and check for conflicts later.
|
||||
diagnostic_controls.Push(diag->control);
|
||||
diagnostic_controls.Push(&diag->control);
|
||||
} else {
|
||||
auto added = seen.Add(&d->TypeInfo(), d->source);
|
||||
if (!added && !d->Is<ast::InternalAttribute>()) {
|
||||
|
@ -2457,13 +2457,13 @@ bool Validator::DiagnosticControls(utils::VectorRef<const ast::DiagnosticControl
|
|||
{
|
||||
std::ostringstream ss;
|
||||
ss << "conflicting diagnostic " << use;
|
||||
AddError(ss.str(), dc->source);
|
||||
AddError(ss.str(), dc->rule_name->source);
|
||||
}
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << "severity of '" << symbols_.NameFor(dc->rule_name->symbol) << "' set to '"
|
||||
<< dc->severity << "' here";
|
||||
AddNote(ss.str(), (*diag_added.value)->source);
|
||||
AddNote(ss.str(), (*diag_added.value)->rule_name->source);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1311,8 +1311,11 @@ Transform::ApplyResult Renamer::Apply(const Program* src,
|
|||
});
|
||||
}
|
||||
},
|
||||
[&](const ast::DiagnosticControl* diagnostic) {
|
||||
preserved_identifiers.Add(diagnostic->rule_name);
|
||||
[&](const ast::DiagnosticAttribute* diagnostic) {
|
||||
preserved_identifiers.Add(diagnostic->control.rule_name);
|
||||
},
|
||||
[&](const ast::DiagnosticDirective* diagnostic) {
|
||||
preserved_identifiers.Add(diagnostic->control.rule_name);
|
||||
},
|
||||
[&](const ast::TypeName* type_name) {
|
||||
if (is_type_short_name(type_name->name->symbol)) {
|
||||
|
|
|
@ -114,7 +114,9 @@ Transform::ApplyResult SingleEntryPoint::Apply(const Program* src,
|
|||
}
|
||||
},
|
||||
[&](const ast::Enable* ext) { b.AST().AddEnable(ctx.Clone(ext)); },
|
||||
[&](const ast::DiagnosticControl* dc) { b.AST().AddDiagnosticControl(ctx.Clone(dc)); },
|
||||
[&](const ast::DiagnosticDirective* d) {
|
||||
b.AST().AddDiagnosticDirective(ctx.Clone(d));
|
||||
},
|
||||
[&](Default) {
|
||||
TINT_UNREACHABLE(Transform, b.Diagnostics())
|
||||
<< "unhandled global declaration: " << decl->TypeInfo().name;
|
||||
|
|
|
@ -250,7 +250,7 @@ bool GeneratorImpl::Generate() {
|
|||
|
||||
auto* mod = builder_.Sem().Module();
|
||||
for (auto* decl : mod->DependencyOrderedDeclarations()) {
|
||||
if (decl->IsAnyOf<ast::Alias, ast::ConstAssert, ast::DiagnosticControl>()) {
|
||||
if (decl->IsAnyOf<ast::Alias, ast::ConstAssert, ast::DiagnosticDirective>()) {
|
||||
continue; // These are not emitted.
|
||||
}
|
||||
|
||||
|
|
|
@ -310,7 +310,7 @@ bool GeneratorImpl::Generate() {
|
|||
|
||||
auto* mod = builder_.Sem().Module();
|
||||
for (auto* decl : mod->DependencyOrderedDeclarations()) {
|
||||
if (decl->IsAnyOf<ast::Alias, ast::DiagnosticControl, ast::Enable, ast::ConstAssert>()) {
|
||||
if (decl->IsAnyOf<ast::Alias, ast::DiagnosticDirective, ast::Enable, ast::ConstAssert>()) {
|
||||
continue; // These are not emitted.
|
||||
}
|
||||
|
||||
|
|
|
@ -313,7 +313,7 @@ bool GeneratorImpl::Generate() {
|
|||
}
|
||||
return EmitFunction(func);
|
||||
},
|
||||
[&](const ast::DiagnosticControl*) {
|
||||
[&](const ast::DiagnosticDirective*) {
|
||||
// Do nothing for diagnostic directives in MSL
|
||||
return true;
|
||||
},
|
||||
|
|
|
@ -71,9 +71,9 @@ bool GeneratorImpl::Generate() {
|
|||
}
|
||||
has_directives = true;
|
||||
}
|
||||
for (auto diagnostic : program_->AST().DiagnosticControls()) {
|
||||
for (auto diagnostic : program_->AST().DiagnosticDirectives()) {
|
||||
auto out = line();
|
||||
if (!EmitDiagnosticControl(out, diagnostic)) {
|
||||
if (!EmitDiagnosticControl(out, diagnostic->control)) {
|
||||
return false;
|
||||
}
|
||||
out << ";";
|
||||
|
@ -84,7 +84,7 @@ bool GeneratorImpl::Generate() {
|
|||
}
|
||||
// Generate global declarations in the order they appear in the module.
|
||||
for (auto* decl : program_->AST().GlobalDeclarations()) {
|
||||
if (decl->IsAnyOf<ast::DiagnosticControl, ast::Enable>()) {
|
||||
if (decl->IsAnyOf<ast::DiagnosticDirective, ast::Enable>()) {
|
||||
continue;
|
||||
}
|
||||
if (!Switch(
|
||||
|
@ -108,9 +108,9 @@ bool GeneratorImpl::Generate() {
|
|||
}
|
||||
|
||||
bool GeneratorImpl::EmitDiagnosticControl(std::ostream& out,
|
||||
const ast::DiagnosticControl* diagnostic) {
|
||||
out << "diagnostic(" << diagnostic->severity << ", "
|
||||
<< program_->Symbols().NameFor(diagnostic->rule_name->symbol) << ")";
|
||||
const ast::DiagnosticControl& diagnostic) {
|
||||
out << "diagnostic(" << diagnostic.severity << ", "
|
||||
<< program_->Symbols().NameFor(diagnostic.rule_name->symbol) << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @param out the output of the expression stream
|
||||
/// @param diagnostic the diagnostic control node
|
||||
/// @returns true if the diagnostic control was emitted
|
||||
bool EmitDiagnosticControl(std::ostream& out, const ast::DiagnosticControl* diagnostic);
|
||||
bool EmitDiagnosticControl(std::ostream& out, const ast::DiagnosticControl& diagnostic);
|
||||
/// Handles generating an enable directive
|
||||
/// @param enable the enable node
|
||||
/// @returns true if the enable directive was emitted
|
||||
|
|
Loading…
Reference in New Issue