ast: Have all decorations derive from base class

This is the first step in unifying the way decorations are parsed - i.e. instead of parsing decorations in different ways based on the predicted grammar that follows, we can parse decorations blocks in a unified way, then later verify what we have is as expected.

`StructDecoration` has been transformed from an `enum class` to a proper class so it can derive from `Decoration`.

Bug: tint:282
Bug: tint:291
Change-Id: Iaf12d266068d03edf695acdf2cd21e6cc3ea8eb3
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31663
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
Ben Clayton 2020-11-03 21:40:20 +00:00 committed by Commit Bot service account
parent 4735f01193
commit 35298800a6
34 changed files with 386 additions and 88 deletions

View File

@ -255,6 +255,8 @@ source_set("libtint_core_src") {
"src/ast/continue_statement.h", "src/ast/continue_statement.h",
"src/ast/decorated_variable.cc", "src/ast/decorated_variable.cc",
"src/ast/decorated_variable.h", "src/ast/decorated_variable.h",
"src/ast/decoration.cc",
"src/ast/decoration.h",
"src/ast/discard_statement.cc", "src/ast/discard_statement.cc",
"src/ast/discard_statement.h", "src/ast/discard_statement.h",
"src/ast/else_statement.cc", "src/ast/else_statement.cc",
@ -311,6 +313,8 @@ source_set("libtint_core_src") {
"src/ast/stride_decoration.h", "src/ast/stride_decoration.h",
"src/ast/struct.cc", "src/ast/struct.cc",
"src/ast/struct.h", "src/ast/struct.h",
"src/ast/struct_block_decoration.cc",
"src/ast/struct_block_decoration.h",
"src/ast/struct_decoration.cc", "src/ast/struct_decoration.cc",
"src/ast/struct_decoration.h", "src/ast/struct_decoration.h",
"src/ast/struct_member.cc", "src/ast/struct_member.cc",
@ -734,6 +738,7 @@ source_set("tint_unittests_core_src") {
"src/ast/case_statement_test.cc", "src/ast/case_statement_test.cc",
"src/ast/constant_id_decoration_test.cc", "src/ast/constant_id_decoration_test.cc",
"src/ast/continue_statement_test.cc", "src/ast/continue_statement_test.cc",
"src/ast/decoration_test.cc",
"src/ast/decorated_variable_test.cc", "src/ast/decorated_variable_test.cc",
"src/ast/discard_statement_test.cc", "src/ast/discard_statement_test.cc",
"src/ast/else_statement_test.cc", "src/ast/else_statement_test.cc",

View File

@ -76,6 +76,8 @@ set(TINT_LIB_SRCS
ast/continue_statement.h ast/continue_statement.h
ast/decorated_variable.cc ast/decorated_variable.cc
ast/decorated_variable.h ast/decorated_variable.h
ast/decoration.cc
ast/decoration.h
ast/discard_statement.cc ast/discard_statement.cc
ast/discard_statement.h ast/discard_statement.h
ast/else_statement.cc ast/else_statement.cc
@ -132,6 +134,8 @@ set(TINT_LIB_SRCS
ast/stride_decoration.h ast/stride_decoration.h
ast/struct.cc ast/struct.cc
ast/struct.h ast/struct.h
ast/struct_block_decoration.cc
ast/struct_block_decoration.h
ast/struct_decoration.cc ast/struct_decoration.cc
ast/struct_decoration.h ast/struct_decoration.h
ast/struct_member.cc ast/struct_member.cc
@ -344,6 +348,7 @@ set(TINT_TEST_SRCS
ast/constant_id_decoration_test.cc ast/constant_id_decoration_test.cc
ast/continue_statement_test.cc ast/continue_statement_test.cc
ast/discard_statement_test.cc ast/discard_statement_test.cc
ast/decoration_test.cc
ast/decorated_variable_test.cc ast/decorated_variable_test.cc
ast/else_statement_test.cc ast/else_statement_test.cc
ast/expression_test.cc ast/expression_test.cc

View File

@ -21,7 +21,7 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
ArrayDecoration::ArrayDecoration() = default; ArrayDecoration::ArrayDecoration() : Decoration(Kind) {}
ArrayDecoration::~ArrayDecoration() = default; ArrayDecoration::~ArrayDecoration() = default;

View File

@ -19,15 +19,20 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "src/ast/decoration.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
class StrideDecoration; class StrideDecoration;
/// A decoration attached to an array /// A decoration attached to an array
class ArrayDecoration { class ArrayDecoration : public Decoration {
public: public:
virtual ~ArrayDecoration(); /// The kind of decoration that this type represents
static constexpr DecorationKind Kind = DecorationKind::kArray;
~ArrayDecoration() override;
/// @returns true if this is a stride decoration /// @returns true if this is a stride decoration
virtual bool IsStride() const; virtual bool IsStride() const;
@ -39,6 +44,7 @@ class ArrayDecoration {
virtual std::string to_str() const = 0; virtual std::string to_str() const = 0;
protected: protected:
/// Constructor
ArrayDecoration(); ArrayDecoration();
}; };

39
src/ast/decoration.cc Normal file
View File

@ -0,0 +1,39 @@
// Copyright 2020 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/ast/decoration.h"
namespace tint {
namespace ast {
Decoration::~Decoration() = default;
std::ostream& operator<<(std::ostream& out, DecorationKind data) {
switch (data) {
case DecorationKind::kArray:
return out << "array";
case DecorationKind::kFunction:
return out << "function";
case DecorationKind::kStruct:
return out << "struct";
case DecorationKind::kStructMember:
return out << "struct member";
case DecorationKind::kVariable:
return out << "variable";
}
return out << "<unknown>";
}
} // namespace ast
} // namespace tint

82
src/ast/decoration.h Normal file
View File

@ -0,0 +1,82 @@
// Copyright 2020 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_AST_DECORATION_H_
#define SRC_AST_DECORATION_H_
#include <memory>
#include <ostream>
#include <vector>
#include "src/source.h"
namespace tint {
namespace ast {
/// The decoration kind enumerator
enum class DecorationKind {
kArray,
kFunction,
kStruct,
kStructMember,
kVariable
};
std::ostream& operator<<(std::ostream& out, DecorationKind data);
/// The base class for all decorations
class Decoration {
public:
virtual ~Decoration();
/// @return the decoration kind
DecorationKind GetKind() const { return kind_; }
/// @return true if this decoration is of (or derives from) type |TO|
template <typename TO>
bool Is() const {
return GetKind() == TO::Kind;
}
protected:
/// Constructor
/// @param kind represents the derived type
explicit Decoration(DecorationKind kind) : kind_(kind) {}
private:
DecorationKind const kind_;
};
/// As dynamically casts |deco| to the target type |TO|.
/// @return the dynamically cast decoration, or nullptr if |deco| is not of the
/// type |TO|.
template <typename TO>
std::unique_ptr<TO> As(std::unique_ptr<Decoration>&& deco) {
if (deco == nullptr) {
return nullptr;
}
if (deco->Is<TO>()) {
auto ptr = static_cast<TO*>(deco.release());
return std::unique_ptr<TO>(ptr);
}
return nullptr;
}
/// A list of unique decorations
using DecorationList = std::vector<std::unique_ptr<Decoration>>;
} // namespace ast
} // namespace tint
#endif // SRC_AST_DECORATION_H_

View File

@ -0,0 +1,53 @@
// Copyright 2020 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/ast/decoration.h"
#include <sstream>
#include <utility>
#include "gtest/gtest.h"
#include "src/ast/array_decoration.h"
#include "src/ast/constant_id_decoration.h"
namespace tint {
namespace ast {
namespace {
using DecorationTest = testing::Test;
TEST_F(DecorationTest, AsCorrectType) {
auto* decoration = new ConstantIdDecoration(1);
auto upcast = std::unique_ptr<Decoration>(decoration);
auto downcast = As<VariableDecoration>(std::move(upcast));
EXPECT_EQ(decoration, downcast.get());
}
TEST_F(DecorationTest, AsIncorrectType) {
auto* decoration = new ConstantIdDecoration(1);
auto upcast = std::unique_ptr<Decoration>(decoration);
auto downcast = As<ArrayDecoration>(std::move(upcast));
EXPECT_EQ(nullptr, downcast.get());
}
TEST_F(DecorationTest, Is) {
auto decoration = std::make_unique<ConstantIdDecoration>(1);
EXPECT_TRUE(decoration->Is<VariableDecoration>());
EXPECT_FALSE(decoration->Is<ArrayDecoration>());
}
} // namespace
} // namespace ast
} // namespace tint

View File

@ -22,7 +22,7 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
FunctionDecoration::FunctionDecoration() = default; FunctionDecoration::FunctionDecoration() : Decoration(Kind) {}
FunctionDecoration::~FunctionDecoration() = default; FunctionDecoration::~FunctionDecoration() = default;

View File

@ -19,6 +19,8 @@
#include <ostream> #include <ostream>
#include <vector> #include <vector>
#include "src/ast/decoration.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
@ -26,9 +28,12 @@ class StageDecoration;
class WorkgroupDecoration; class WorkgroupDecoration;
/// A decoration attached to a function /// A decoration attached to a function
class FunctionDecoration { class FunctionDecoration : public Decoration {
public: public:
virtual ~FunctionDecoration(); /// The kind of decoration that this type represents
static constexpr DecorationKind Kind = DecorationKind::kFunction;
~FunctionDecoration() override;
/// @returns true if this is a stage decoration /// @returns true if this is a stage decoration
virtual bool IsStage() const; virtual bool IsStage() const;
@ -42,11 +47,10 @@ class FunctionDecoration {
/// Outputs the function decoration to the given stream /// Outputs the function decoration to the given stream
/// @param out the stream to output too /// @param out the stream to output too
//! @cond Doxygen_Suppress
virtual void to_str(std::ostream& out) const = 0; virtual void to_str(std::ostream& out) const = 0;
//! @endcond
protected: protected:
/// Constructor
FunctionDecoration(); FunctionDecoration();
}; };

View File

@ -23,7 +23,9 @@ Struct::Struct(StructMemberList members)
: Node(), members_(std::move(members)) {} : Node(), members_(std::move(members)) {}
Struct::Struct(StructDecorationList decorations, StructMemberList members) Struct::Struct(StructDecorationList decorations, StructMemberList members)
: Node(), decorations_(decorations), members_(std::move(members)) {} : Node(),
decorations_(std::move(decorations)),
members_(std::move(members)) {}
Struct::Struct(const Source& source, StructMemberList members) Struct::Struct(const Source& source, StructMemberList members)
: Node(source), members_(std::move(members)) {} : Node(source), members_(std::move(members)) {}
@ -31,7 +33,9 @@ Struct::Struct(const Source& source, StructMemberList members)
Struct::Struct(const Source& source, Struct::Struct(const Source& source,
StructDecorationList decorations, StructDecorationList decorations,
StructMemberList members) StructMemberList members)
: Node(source), decorations_(decorations), members_(std::move(members)) {} : Node(source),
decorations_(std::move(decorations)),
members_(std::move(members)) {}
Struct::Struct(Struct&&) = default; Struct::Struct(Struct&&) = default;
@ -47,8 +51,8 @@ StructMember* Struct::get_member(const std::string& name) const {
} }
bool Struct::IsBlockDecorated() const { bool Struct::IsBlockDecorated() const {
for (auto deco : decorations_) { for (auto& deco : decorations_) {
if (deco == StructDecoration::kBlock) { if (deco->IsBlock()) {
return true; return true;
} }
} }
@ -56,11 +60,6 @@ bool Struct::IsBlockDecorated() const {
} }
bool Struct::IsValid() const { bool Struct::IsValid() const {
for (auto deco : decorations_) {
if (deco == StructDecoration::kNone) {
return false;
}
}
for (const auto& mem : members_) { for (const auto& mem : members_) {
if (mem == nullptr || !mem->IsValid()) { if (mem == nullptr || !mem->IsValid()) {
return false; return false;
@ -71,9 +70,11 @@ bool Struct::IsValid() const {
void Struct::to_str(std::ostream& out, size_t indent) const { void Struct::to_str(std::ostream& out, size_t indent) const {
out << "Struct{" << std::endl; out << "Struct{" << std::endl;
for (auto deco : decorations_) { for (auto& deco : decorations_) {
make_indent(out, indent + 2); make_indent(out, indent + 2);
out << "[[" << deco << "]]" << std::endl; out << "[[";
deco->to_str(out);
out << "]]" << std::endl;
} }
for (const auto& member : members_) { for (const auto& member : members_) {
member->to_str(out, indent + 2); member->to_str(out, indent + 2);

View File

@ -0,0 +1,33 @@
// Copyright 2020 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/ast/struct_block_decoration.h"
namespace tint {
namespace ast {
StructBlockDecoration::StructBlockDecoration() = default;
StructBlockDecoration::~StructBlockDecoration() = default;
bool StructBlockDecoration::IsBlock() const {
return true;
}
void StructBlockDecoration::to_str(std::ostream& out) const {
out << "block";
}
} // namespace ast
} // namespace tint

View File

@ -0,0 +1,48 @@
// Copyright 2020 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_AST_STRUCT_BLOCK_DECORATION_H_
#define SRC_AST_STRUCT_BLOCK_DECORATION_H_
#include <memory>
#include <ostream>
#include <vector>
#include "src/ast/struct_decoration.h"
namespace tint {
namespace ast {
/// The struct decorations
class StructBlockDecoration : public StructDecoration {
public:
/// constructor
StructBlockDecoration();
~StructBlockDecoration() override;
/// @returns true if this is a block struct
bool IsBlock() const override;
/// Outputs the decoration to the given stream
/// @param out the stream to output too
void to_str(std::ostream& out) const override;
};
/// List of struct decorations
using StructDecorationList = std::vector<std::unique_ptr<StructDecoration>>;
} // namespace ast
} // namespace tint
#endif // SRC_AST_STRUCT_BLOCK_DECORATION_H_

View File

@ -17,19 +17,9 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
std::ostream& operator<<(std::ostream& out, StructDecoration stage) { StructDecoration::StructDecoration() : Decoration(Kind) {}
switch (stage) {
case StructDecoration::kNone: { StructDecoration::~StructDecoration() = default;
out << "none";
break;
}
case StructDecoration::kBlock: {
out << "block";
break;
}
}
return out;
}
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -15,19 +15,37 @@
#ifndef SRC_AST_STRUCT_DECORATION_H_ #ifndef SRC_AST_STRUCT_DECORATION_H_
#define SRC_AST_STRUCT_DECORATION_H_ #define SRC_AST_STRUCT_DECORATION_H_
#include <memory>
#include <ostream> #include <ostream>
#include <vector> #include <vector>
#include "src/ast/decoration.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
/// The struct decorations /// The struct decorations
enum class StructDecoration { kNone = -1, kBlock }; class StructDecoration : public Decoration {
public:
/// The kind of decoration that this type represents
static constexpr DecorationKind Kind = DecorationKind::kStruct;
std::ostream& operator<<(std::ostream& out, StructDecoration stage); ~StructDecoration() override;
/// @returns true if this is a block struct
virtual bool IsBlock() const = 0;
/// Outputs the decoration to the given stream
/// @param out the stream to output too
virtual void to_str(std::ostream& out) const = 0;
protected:
/// Constructor
StructDecoration();
};
/// List of struct decorations /// List of struct decorations
using StructDecorationList = std::vector<StructDecoration>; using StructDecorationList = std::vector<std::unique_ptr<StructDecoration>>;
} // namespace ast } // namespace ast
} // namespace tint } // namespace tint

View File

@ -21,7 +21,8 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
StructMemberDecoration::StructMemberDecoration() = default; StructMemberDecoration::StructMemberDecoration()
: Decoration(DecorationKind::kStructMember) {}
StructMemberDecoration::~StructMemberDecoration() = default; StructMemberDecoration::~StructMemberDecoration() = default;

View File

@ -19,15 +19,20 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "src/ast/decoration.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
class StructMemberOffsetDecoration; class StructMemberOffsetDecoration;
/// A decoration attached to a struct member /// A decoration attached to a struct member
class StructMemberDecoration { class StructMemberDecoration : public Decoration {
public: public:
virtual ~StructMemberDecoration(); /// The kind of decoration that this type represents
static constexpr DecorationKind Kind = DecorationKind::kStructMember;
~StructMemberDecoration() override;
/// @returns true if this is an offset decoration /// @returns true if this is an offset decoration
virtual bool IsOffset() const; virtual bool IsOffset() const;
@ -39,6 +44,7 @@ class StructMemberDecoration {
virtual std::string to_str() const = 0; virtual std::string to_str() const = 0;
protected: protected:
/// Constructor
StructMemberDecoration(); StructMemberDecoration();
}; };

View File

@ -19,7 +19,7 @@
#include <utility> #include <utility>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/type/i32_type.h" #include "src/ast/type/i32_type.h"
@ -52,12 +52,12 @@ TEST_F(StructTest, Creation_WithDecorations) {
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos; StructDecorationList decos;
decos.push_back(StructDecoration::kBlock); decos.push_back(std::make_unique<StructBlockDecoration>());
Struct s{std::move(decos), std::move(members)}; Struct s{std::move(decos), std::move(members)};
EXPECT_EQ(s.members().size(), 1u); EXPECT_EQ(s.members().size(), 1u);
ASSERT_EQ(s.decorations().size(), 1u); ASSERT_EQ(s.decorations().size(), 1u);
EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock); EXPECT_TRUE(s.decorations()[0]->IsBlock());
EXPECT_EQ(s.source().range.begin.line, 0u); EXPECT_EQ(s.source().range.begin.line, 0u);
EXPECT_EQ(s.source().range.begin.column, 0u); EXPECT_EQ(s.source().range.begin.column, 0u);
EXPECT_EQ(s.source().range.end.line, 0u); EXPECT_EQ(s.source().range.end.line, 0u);
@ -72,14 +72,14 @@ TEST_F(StructTest, CreationWithSourceAndDecorations) {
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos; StructDecorationList decos;
decos.push_back(StructDecoration::kBlock); decos.push_back(std::make_unique<StructBlockDecoration>());
Struct s{ Struct s{
Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}}, Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}},
std::move(decos), std::move(members)}; std::move(decos), std::move(members)};
EXPECT_EQ(s.members().size(), 1u); EXPECT_EQ(s.members().size(), 1u);
ASSERT_EQ(s.decorations().size(), 1u); ASSERT_EQ(s.decorations().size(), 1u);
EXPECT_EQ(s.decorations()[0], StructDecoration::kBlock); EXPECT_TRUE(s.decorations()[0]->IsBlock());
EXPECT_EQ(s.source().range.begin.line, 27u); EXPECT_EQ(s.source().range.begin.line, 27u);
EXPECT_EQ(s.source().range.begin.column, 4u); EXPECT_EQ(s.source().range.begin.column, 4u);
EXPECT_EQ(s.source().range.end.line, 27u); EXPECT_EQ(s.source().range.end.line, 27u);
@ -114,20 +114,6 @@ TEST_F(StructTest, IsValid_Invalid_StructMember) {
EXPECT_FALSE(s.IsValid()); EXPECT_FALSE(s.IsValid());
} }
TEST_F(StructTest, IsValid_NoneDecoration) {
type::I32Type i32;
StructMemberList members;
members.push_back(
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos;
decos.push_back(StructDecoration::kNone);
Struct s{std::move(decos), std::move(members)};
EXPECT_FALSE(s.IsValid());
}
TEST_F(StructTest, ToStr) { TEST_F(StructTest, ToStr) {
type::I32Type i32; type::I32Type i32;
@ -136,7 +122,7 @@ TEST_F(StructTest, ToStr) {
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList())); std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos; StructDecorationList decos;
decos.push_back(StructDecoration::kBlock); decos.push_back(std::make_unique<StructBlockDecoration>());
Struct s{std::move(decos), std::move(members)}; Struct s{std::move(decos), std::move(members)};

View File

@ -14,6 +14,9 @@
#include "src/ast/type/access_control_type.h" #include "src/ast/type/access_control_type.h"
#include <memory>
#include <utility>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/storage_class.h" #include "src/ast/storage_class.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"

View File

@ -14,6 +14,9 @@
#include "src/ast/type/alias_type.h" #include "src/ast/type/alias_type.h"
#include <memory>
#include <utility>
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/storage_class.h" #include "src/ast/storage_class.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"

View File

@ -25,7 +25,7 @@
namespace tint { namespace tint {
namespace ast { namespace ast {
VariableDecoration::VariableDecoration() = default; VariableDecoration::VariableDecoration() : Decoration(Kind) {}
VariableDecoration::~VariableDecoration() = default; VariableDecoration::~VariableDecoration() = default;

View File

@ -20,6 +20,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "src/ast/decoration.h"
namespace tint { namespace tint {
namespace ast { namespace ast {
@ -30,9 +32,12 @@ class LocationDecoration;
class SetDecoration; class SetDecoration;
/// A decoration attached to a variable /// A decoration attached to a variable
class VariableDecoration { class VariableDecoration : public Decoration {
public: public:
virtual ~VariableDecoration(); /// The kind of decoration that this type represents
static constexpr DecorationKind Kind = DecorationKind::kVariable;
~VariableDecoration() override;
/// @returns true if this is a binding decoration /// @returns true if this is a binding decoration
virtual bool IsBinding() const; virtual bool IsBinding() const;
@ -58,11 +63,10 @@ class VariableDecoration {
/// Outputs the variable decoration to the given stream /// Outputs the variable decoration to the given stream
/// @param out the stream to output too /// @param out the stream to output too
//! @cond Doxygen_Suppress
virtual void to_str(std::ostream& out) const = 0; virtual void to_str(std::ostream& out) const = 0;
//! @endcond
protected: protected:
/// Constructor
VariableDecoration(); VariableDecoration();
}; };

View File

@ -34,6 +34,7 @@
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h" #include "src/ast/stage_decoration.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h" #include "src/ast/struct_member_decoration.h"
@ -268,7 +269,7 @@ class InspectorHelper {
ast::StructDecorationList decos; ast::StructDecorationList decos;
if (is_block) { if (is_block) {
decos.push_back(ast::StructDecoration::kBlock); decos.push_back(std::make_unique<ast::StructBlockDecoration>());
} }
auto str = auto str =

View File

@ -48,6 +48,7 @@
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h" #include "src/ast/struct_member_decoration.h"
@ -802,9 +803,11 @@ ast::type::Type* ParserImpl::ConvertType(
if (struct_decorations.size() == 1) { if (struct_decorations.size() == 1) {
const auto decoration = struct_decorations[0][0]; const auto decoration = struct_decorations[0][0];
if (decoration == SpvDecorationBlock) { if (decoration == SpvDecorationBlock) {
ast_struct_decorations.push_back(ast::StructDecoration::kBlock); ast_struct_decorations.push_back(
std::make_unique<ast::StructBlockDecoration>());
} else if (decoration == SpvDecorationBufferBlock) { } else if (decoration == SpvDecorationBufferBlock) {
ast_struct_decorations.push_back(ast::StructDecoration::kBlock); ast_struct_decorations.push_back(
std::make_unique<ast::StructBlockDecoration>());
remap_buffer_block_type_.insert(type_id); remap_buffer_block_type_.insert(type_id);
} else { } else {
Fail() << "struct with ID " << type_id Fail() << "struct with ID " << type_id

View File

@ -42,6 +42,7 @@
#include "src/ast/sint_literal.h" #include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h" #include "src/ast/stage_decoration.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_member_offset_decoration.h" #include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/switch_statement.h" #include "src/ast/switch_statement.h"
#include "src/ast/type/alias_type.h" #include "src/ast/type/alias_type.h"
@ -1524,10 +1525,10 @@ bool ParserImpl::struct_decoration_decl(ast::StructDecorationList& decos) {
if (has_error()) { if (has_error()) {
return false; return false;
} }
if (deco == ast::StructDecoration::kNone) { if (deco == nullptr) {
return true; return true;
} }
decos.push_back(deco); decos.emplace_back(std::move(deco));
next(); // Consume the peek of [[ next(); // Consume the peek of [[
next(); // Consume the peek from the struct_decoration next(); // Consume the peek from the struct_decoration
@ -1543,11 +1544,11 @@ bool ParserImpl::struct_decoration_decl(ast::StructDecorationList& decos) {
// struct_decoration // struct_decoration
// : BLOCK // : BLOCK
ast::StructDecoration ParserImpl::struct_decoration(Token t) { std::unique_ptr<ast::StructDecoration> ParserImpl::struct_decoration(Token t) {
if (t.IsBlock()) { if (t.IsBlock()) {
return ast::StructDecoration::kBlock; return std::make_unique<ast::StructBlockDecoration>();
} }
return ast::StructDecoration::kNone; return nullptr;
} }
// struct_body_decl // struct_body_decl

View File

@ -189,7 +189,7 @@ class ParserImpl {
/// Parses a `struct_decoration` grammar element /// Parses a `struct_decoration` grammar element
/// @param t the current token /// @param t the current token
/// @returns the struct decoration or StructDecoraton::kNone if none matched /// @returns the struct decoration or StructDecoraton::kNone if none matched
ast::StructDecoration struct_decoration(Token t); std::unique_ptr<ast::StructDecoration> struct_decoration(Token t);
/// Parses a `struct_body_decl` grammar element /// Parses a `struct_body_decl` grammar element
/// @returns the struct members /// @returns the struct members
ast::StructMemberList struct_body_decl(); ast::StructMemberList struct_body_decl();

View File

@ -51,7 +51,7 @@ TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
EXPECT_EQ(s->impl()->members()[0]->name(), "a"); EXPECT_EQ(s->impl()->members()[0]->name(), "a");
EXPECT_EQ(s->impl()->members()[1]->name(), "b"); EXPECT_EQ(s->impl()->members()[1]->name(), "b");
ASSERT_EQ(s->impl()->decorations().size(), 1u); ASSERT_EQ(s->impl()->decorations().size(), 1u);
EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock); EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
} }
TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) { TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
@ -69,8 +69,8 @@ TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
EXPECT_EQ(s->impl()->members()[0]->name(), "a"); EXPECT_EQ(s->impl()->members()[0]->name(), "a");
EXPECT_EQ(s->impl()->members()[1]->name(), "b"); EXPECT_EQ(s->impl()->members()[1]->name(), "b");
ASSERT_EQ(s->impl()->decorations().size(), 2u); ASSERT_EQ(s->impl()->decorations().size(), 2u);
EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock); EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
EXPECT_EQ(s->impl()->decorations()[1], ast::StructDecoration::kBlock); EXPECT_TRUE(s->impl()->decorations()[1]->IsBlock());
} }
TEST_F(ParserImplTest, StructDecl_EmptyMembers) { TEST_F(ParserImplTest, StructDecl_EmptyMembers) {

View File

@ -27,7 +27,7 @@ TEST_F(ParserImplTest, StructDecorationDecl_Parses) {
ASSERT_TRUE(p->struct_decoration_decl(decos)); ASSERT_TRUE(p->struct_decoration_decl(decos));
ASSERT_FALSE(p->has_error()); ASSERT_FALSE(p->has_error());
EXPECT_EQ(decos.size(), 1u); EXPECT_EQ(decos.size(), 1u);
EXPECT_EQ(decos[0], ast::StructDecoration::kBlock); EXPECT_TRUE(decos[0]->IsBlock());
} }
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) { TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {

View File

@ -24,7 +24,7 @@ namespace {
struct StructDecorationData { struct StructDecorationData {
const char* input; const char* input;
ast::StructDecoration result; bool is_block;
}; };
inline std::ostream& operator<<(std::ostream& out, StructDecorationData data) { inline std::ostream& operator<<(std::ostream& out, StructDecorationData data) {
out << std::string(data.input); out << std::string(data.input);
@ -40,17 +40,16 @@ TEST_P(StructDecorationTest, Parses) {
auto deco = p->struct_decoration(p->peek()); auto deco = p->struct_decoration(p->peek());
ASSERT_FALSE(p->has_error()); ASSERT_FALSE(p->has_error());
EXPECT_EQ(deco, params.result); EXPECT_EQ(deco->IsBlock(), params.is_block);
} }
INSTANTIATE_TEST_SUITE_P(ParserImplTest, INSTANTIATE_TEST_SUITE_P(ParserImplTest,
StructDecorationTest, StructDecorationTest,
testing::Values(StructDecorationData{ testing::Values(StructDecorationData{"block", true}));
"block", ast::StructDecoration::kBlock}));
TEST_F(ParserImplTest, StructDecoration_NoMatch) { TEST_F(ParserImplTest, StructDecoration_NoMatch) {
auto* p = parser("not-a-stage"); auto* p = parser("not-a-stage");
auto deco = p->struct_decoration(p->peek()); auto deco = p->struct_decoration(p->peek());
ASSERT_EQ(deco, ast::StructDecoration::kNone); ASSERT_EQ(deco, nullptr);
auto t = p->next(); auto t = p->next();
EXPECT_TRUE(t.IsIdentifier()); EXPECT_TRUE(t.IsIdentifier());

View File

@ -25,6 +25,7 @@
#include "src/ast/scalar_constructor_expression.h" #include "src/ast/scalar_constructor_expression.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h" #include "src/ast/struct_member_offset_decoration.h"
@ -234,7 +235,7 @@ void VertexPullingTransform::AddVertexStorageBuffers() {
kStructBufferName, internal_array_type, std::move(member_dec))); kStructBufferName, internal_array_type, std::move(member_dec)));
ast::StructDecorationList decos; ast::StructDecorationList decos;
decos.push_back(ast::StructDecoration::kBlock); decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto* struct_type = auto* struct_type =
ctx_->type_mgr().Get(std::make_unique<ast::type::StructType>( ctx_->type_mgr().Get(std::make_unique<ast::type::StructType>(

View File

@ -14,6 +14,7 @@
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h" #include "src/ast/struct_member_decoration.h"
@ -286,7 +287,7 @@ TEST_F(HlslGeneratorImplTest_Type, DISABLED_EmitType_Struct_WithDecoration) {
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
ast::StructDecorationList decos; ast::StructDecorationList decos;
decos.push_back(ast::StructDecoration::kBlock); decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto str = auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members)); std::make_unique<ast::Struct>(std::move(decos), std::move(members));

View File

@ -15,6 +15,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/module.h" #include "src/ast/module.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h" #include "src/ast/struct_member_decoration.h"
@ -324,7 +325,7 @@ TEST_F(MslGeneratorImplTest, DISABLED_EmitType_Struct_WithDecoration) {
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
ast::StructDecorationList decos; ast::StructDecorationList decos;
decos.push_back(ast::StructDecoration::kBlock); decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto str = auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members)); std::make_unique<ast::Struct>(std::move(decos), std::move(members));

View File

@ -18,6 +18,7 @@
#include "src/ast/identifier_expression.h" #include "src/ast/identifier_expression.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h" #include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/type/access_control_type.h" #include "src/ast/type/access_control_type.h"
@ -361,7 +362,7 @@ TEST_F(BuilderTest_Type, GenerateStruct_Decorated) {
std::make_unique<ast::StructMember>("a", &f32, std::move(decos))); std::make_unique<ast::StructMember>("a", &f32, std::move(decos)));
ast::StructDecorationList struct_decos; ast::StructDecorationList struct_decos;
struct_decos.push_back(ast::StructDecoration::kBlock); struct_decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto s = std::make_unique<ast::Struct>(std::move(struct_decos), auto s = std::make_unique<ast::Struct>(std::move(struct_decos),
std::move(members)); std::move(members));

View File

@ -552,8 +552,10 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) {
bool GeneratorImpl::EmitStructType(const ast::type::StructType* str) { bool GeneratorImpl::EmitStructType(const ast::type::StructType* str) {
auto* impl = str->impl(); auto* impl = str->impl();
for (auto deco : impl->decorations()) { for (auto& deco : impl->decorations()) {
out_ << "[[" << deco << "]]" << std::endl; out_ << "[[";
deco->to_str(out_);
out_ << "]]" << std::endl;
} }
out_ << "struct " << str->name() << " {" << std::endl; out_ << "struct " << str->name() << " {" << std::endl;

View File

@ -15,6 +15,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "src/ast/stride_decoration.h" #include "src/ast/stride_decoration.h"
#include "src/ast/struct.h" #include "src/ast/struct.h"
#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h" #include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h" #include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h" #include "src/ast/struct_member_decoration.h"
@ -204,7 +205,7 @@ TEST_F(WgslGeneratorImplTest, EmitType_Struct_WithDecoration) {
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco))); std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
ast::StructDecorationList decos; ast::StructDecorationList decos;
decos.push_back(ast::StructDecoration::kBlock); decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto str = auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members)); std::make_unique<ast::Struct>(std::move(decos), std::move(members));