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>
diff --git a/BUILD.gn b/BUILD.gn
index 2165569..1a1aae1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -255,6 +255,8 @@
"src/ast/continue_statement.h",
"src/ast/decorated_variable.cc",
"src/ast/decorated_variable.h",
+ "src/ast/decoration.cc",
+ "src/ast/decoration.h",
"src/ast/discard_statement.cc",
"src/ast/discard_statement.h",
"src/ast/else_statement.cc",
@@ -311,6 +313,8 @@
"src/ast/stride_decoration.h",
"src/ast/struct.cc",
"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.h",
"src/ast/struct_member.cc",
@@ -734,6 +738,7 @@
"src/ast/case_statement_test.cc",
"src/ast/constant_id_decoration_test.cc",
"src/ast/continue_statement_test.cc",
+ "src/ast/decoration_test.cc",
"src/ast/decorated_variable_test.cc",
"src/ast/discard_statement_test.cc",
"src/ast/else_statement_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0eff8bd..f5e1945 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -76,6 +76,8 @@
ast/continue_statement.h
ast/decorated_variable.cc
ast/decorated_variable.h
+ ast/decoration.cc
+ ast/decoration.h
ast/discard_statement.cc
ast/discard_statement.h
ast/else_statement.cc
@@ -132,6 +134,8 @@
ast/stride_decoration.h
ast/struct.cc
ast/struct.h
+ ast/struct_block_decoration.cc
+ ast/struct_block_decoration.h
ast/struct_decoration.cc
ast/struct_decoration.h
ast/struct_member.cc
@@ -344,6 +348,7 @@
ast/constant_id_decoration_test.cc
ast/continue_statement_test.cc
ast/discard_statement_test.cc
+ ast/decoration_test.cc
ast/decorated_variable_test.cc
ast/else_statement_test.cc
ast/expression_test.cc
diff --git a/src/ast/array_decoration.cc b/src/ast/array_decoration.cc
index 8402439..96da686 100644
--- a/src/ast/array_decoration.cc
+++ b/src/ast/array_decoration.cc
@@ -21,7 +21,7 @@
namespace tint {
namespace ast {
-ArrayDecoration::ArrayDecoration() = default;
+ArrayDecoration::ArrayDecoration() : Decoration(Kind) {}
ArrayDecoration::~ArrayDecoration() = default;
diff --git a/src/ast/array_decoration.h b/src/ast/array_decoration.h
index 579668b..a86a4df 100644
--- a/src/ast/array_decoration.h
+++ b/src/ast/array_decoration.h
@@ -19,15 +19,20 @@
#include <string>
#include <vector>
+#include "src/ast/decoration.h"
+
namespace tint {
namespace ast {
class StrideDecoration;
/// A decoration attached to an array
-class ArrayDecoration {
+class ArrayDecoration : public Decoration {
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
virtual bool IsStride() const;
@@ -39,6 +44,7 @@
virtual std::string to_str() const = 0;
protected:
+ /// Constructor
ArrayDecoration();
};
diff --git a/src/ast/decoration.cc b/src/ast/decoration.cc
new file mode 100644
index 0000000..c4abc90
--- /dev/null
+++ b/src/ast/decoration.cc
@@ -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
diff --git a/src/ast/decoration.h b/src/ast/decoration.h
new file mode 100644
index 0000000..9c58cca
--- /dev/null
+++ b/src/ast/decoration.h
@@ -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_
diff --git a/src/ast/decoration_test.cc b/src/ast/decoration_test.cc
new file mode 100644
index 0000000..a800494
--- /dev/null
+++ b/src/ast/decoration_test.cc
@@ -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
diff --git a/src/ast/function_decoration.cc b/src/ast/function_decoration.cc
index d94c2c1..15d7eaa 100644
--- a/src/ast/function_decoration.cc
+++ b/src/ast/function_decoration.cc
@@ -22,7 +22,7 @@
namespace tint {
namespace ast {
-FunctionDecoration::FunctionDecoration() = default;
+FunctionDecoration::FunctionDecoration() : Decoration(Kind) {}
FunctionDecoration::~FunctionDecoration() = default;
diff --git a/src/ast/function_decoration.h b/src/ast/function_decoration.h
index d767138..101f3a9 100644
--- a/src/ast/function_decoration.h
+++ b/src/ast/function_decoration.h
@@ -19,6 +19,8 @@
#include <ostream>
#include <vector>
+#include "src/ast/decoration.h"
+
namespace tint {
namespace ast {
@@ -26,9 +28,12 @@
class WorkgroupDecoration;
/// A decoration attached to a function
-class FunctionDecoration {
+class FunctionDecoration : public Decoration {
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
virtual bool IsStage() const;
@@ -42,11 +47,10 @@
/// Outputs the function decoration to the given stream
/// @param out the stream to output too
- //! @cond Doxygen_Suppress
virtual void to_str(std::ostream& out) const = 0;
- //! @endcond
protected:
+ /// Constructor
FunctionDecoration();
};
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index cf3a02c..8f1e23b 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -23,7 +23,9 @@
: Node(), members_(std::move(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)
: Node(source), members_(std::move(members)) {}
@@ -31,7 +33,9 @@
Struct::Struct(const Source& source,
StructDecorationList decorations,
StructMemberList members)
- : Node(source), decorations_(decorations), members_(std::move(members)) {}
+ : Node(source),
+ decorations_(std::move(decorations)),
+ members_(std::move(members)) {}
Struct::Struct(Struct&&) = default;
@@ -47,8 +51,8 @@
}
bool Struct::IsBlockDecorated() const {
- for (auto deco : decorations_) {
- if (deco == StructDecoration::kBlock) {
+ for (auto& deco : decorations_) {
+ if (deco->IsBlock()) {
return true;
}
}
@@ -56,11 +60,6 @@
}
bool Struct::IsValid() const {
- for (auto deco : decorations_) {
- if (deco == StructDecoration::kNone) {
- return false;
- }
- }
for (const auto& mem : members_) {
if (mem == nullptr || !mem->IsValid()) {
return false;
@@ -71,9 +70,11 @@
void Struct::to_str(std::ostream& out, size_t indent) const {
out << "Struct{" << std::endl;
- for (auto deco : decorations_) {
+ for (auto& deco : decorations_) {
make_indent(out, indent + 2);
- out << "[[" << deco << "]]" << std::endl;
+ out << "[[";
+ deco->to_str(out);
+ out << "]]" << std::endl;
}
for (const auto& member : members_) {
member->to_str(out, indent + 2);
diff --git a/src/ast/struct_block_decoration.cc b/src/ast/struct_block_decoration.cc
new file mode 100644
index 0000000..aac4c21
--- /dev/null
+++ b/src/ast/struct_block_decoration.cc
@@ -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
diff --git a/src/ast/struct_block_decoration.h b/src/ast/struct_block_decoration.h
new file mode 100644
index 0000000..e5f4eaf
--- /dev/null
+++ b/src/ast/struct_block_decoration.h
@@ -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_
diff --git a/src/ast/struct_decoration.cc b/src/ast/struct_decoration.cc
index 10ee485..f75e16b 100644
--- a/src/ast/struct_decoration.cc
+++ b/src/ast/struct_decoration.cc
@@ -17,19 +17,9 @@
namespace tint {
namespace ast {
-std::ostream& operator<<(std::ostream& out, StructDecoration stage) {
- switch (stage) {
- case StructDecoration::kNone: {
- out << "none";
- break;
- }
- case StructDecoration::kBlock: {
- out << "block";
- break;
- }
- }
- return out;
-}
+StructDecoration::StructDecoration() : Decoration(Kind) {}
+
+StructDecoration::~StructDecoration() = default;
} // namespace ast
} // namespace tint
diff --git a/src/ast/struct_decoration.h b/src/ast/struct_decoration.h
index 20139ac..9386e42 100644
--- a/src/ast/struct_decoration.h
+++ b/src/ast/struct_decoration.h
@@ -15,19 +15,37 @@
#ifndef SRC_AST_STRUCT_DECORATION_H_
#define SRC_AST_STRUCT_DECORATION_H_
+#include <memory>
#include <ostream>
#include <vector>
+#include "src/ast/decoration.h"
+
namespace tint {
namespace ast {
/// 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
-using StructDecorationList = std::vector<StructDecoration>;
+using StructDecorationList = std::vector<std::unique_ptr<StructDecoration>>;
} // namespace ast
} // namespace tint
diff --git a/src/ast/struct_member_decoration.cc b/src/ast/struct_member_decoration.cc
index 1c4d154..1e35fd4 100644
--- a/src/ast/struct_member_decoration.cc
+++ b/src/ast/struct_member_decoration.cc
@@ -21,7 +21,8 @@
namespace tint {
namespace ast {
-StructMemberDecoration::StructMemberDecoration() = default;
+StructMemberDecoration::StructMemberDecoration()
+ : Decoration(DecorationKind::kStructMember) {}
StructMemberDecoration::~StructMemberDecoration() = default;
diff --git a/src/ast/struct_member_decoration.h b/src/ast/struct_member_decoration.h
index b54f3eb..b8cbb8a 100644
--- a/src/ast/struct_member_decoration.h
+++ b/src/ast/struct_member_decoration.h
@@ -19,15 +19,20 @@
#include <string>
#include <vector>
+#include "src/ast/decoration.h"
+
namespace tint {
namespace ast {
class StructMemberOffsetDecoration;
/// A decoration attached to a struct member
-class StructMemberDecoration {
+class StructMemberDecoration : public Decoration {
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
virtual bool IsOffset() const;
@@ -39,6 +44,7 @@
virtual std::string to_str() const = 0;
protected:
+ /// Constructor
StructMemberDecoration();
};
diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc
index 55abf23..95f8adb 100644
--- a/src/ast/struct_test.cc
+++ b/src/ast/struct_test.cc
@@ -19,7 +19,7 @@
#include <utility>
#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/type/i32_type.h"
@@ -52,12 +52,12 @@
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos;
- decos.push_back(StructDecoration::kBlock);
+ decos.push_back(std::make_unique<StructBlockDecoration>());
Struct s{std::move(decos), std::move(members)};
EXPECT_EQ(s.members().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.column, 0u);
EXPECT_EQ(s.source().range.end.line, 0u);
@@ -72,14 +72,14 @@
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos;
- decos.push_back(StructDecoration::kBlock);
+ decos.push_back(std::make_unique<StructBlockDecoration>());
Struct s{
Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}},
std::move(decos), std::move(members)};
EXPECT_EQ(s.members().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.column, 4u);
EXPECT_EQ(s.source().range.end.line, 27u);
@@ -114,20 +114,6 @@
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) {
type::I32Type i32;
@@ -136,7 +122,7 @@
std::make_unique<StructMember>("a", &i32, StructMemberDecorationList()));
StructDecorationList decos;
- decos.push_back(StructDecoration::kBlock);
+ decos.push_back(std::make_unique<StructBlockDecoration>());
Struct s{std::move(decos), std::move(members)};
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index cfb3eb0..6dc716e 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -14,6 +14,9 @@
#include "src/ast/type/access_control_type.h"
+#include <memory>
+#include <utility>
+
#include "gtest/gtest.h"
#include "src/ast/storage_class.h"
#include "src/ast/stride_decoration.h"
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 1b5dbc0..6266cfb 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -14,6 +14,9 @@
#include "src/ast/type/alias_type.h"
+#include <memory>
+#include <utility>
+
#include "gtest/gtest.h"
#include "src/ast/storage_class.h"
#include "src/ast/stride_decoration.h"
diff --git a/src/ast/variable_decoration.cc b/src/ast/variable_decoration.cc
index fff88be..2087e68 100644
--- a/src/ast/variable_decoration.cc
+++ b/src/ast/variable_decoration.cc
@@ -25,7 +25,7 @@
namespace tint {
namespace ast {
-VariableDecoration::VariableDecoration() = default;
+VariableDecoration::VariableDecoration() : Decoration(Kind) {}
VariableDecoration::~VariableDecoration() = default;
diff --git a/src/ast/variable_decoration.h b/src/ast/variable_decoration.h
index 8cc5f70..3a13b68 100644
--- a/src/ast/variable_decoration.h
+++ b/src/ast/variable_decoration.h
@@ -20,6 +20,8 @@
#include <string>
#include <vector>
+#include "src/ast/decoration.h"
+
namespace tint {
namespace ast {
@@ -30,9 +32,12 @@
class SetDecoration;
/// A decoration attached to a variable
-class VariableDecoration {
+class VariableDecoration : public Decoration {
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
virtual bool IsBinding() const;
@@ -58,11 +63,10 @@
/// Outputs the variable decoration to the given stream
/// @param out the stream to output too
- //! @cond Doxygen_Suppress
virtual void to_str(std::ostream& out) const = 0;
- //! @endcond
protected:
+ /// Constructor
VariableDecoration();
};
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index f3665e7..97d04f7 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -34,6 +34,7 @@
#include "src/ast/sint_literal.h"
#include "src/ast/stage_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_member.h"
#include "src/ast/struct_member_decoration.h"
@@ -268,7 +269,7 @@
ast::StructDecorationList decos;
if (is_block) {
- decos.push_back(ast::StructDecoration::kBlock);
+ decos.push_back(std::make_unique<ast::StructBlockDecoration>());
}
auto str =
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index d38e96c..ab77baf 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -48,6 +48,7 @@
#include "src/ast/sint_literal.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h"
@@ -802,9 +803,11 @@
if (struct_decorations.size() == 1) {
const auto decoration = struct_decorations[0][0];
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) {
- 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);
} else {
Fail() << "struct with ID " << type_id
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index eb43221..a938eca 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -42,6 +42,7 @@
#include "src/ast/sint_literal.h"
#include "src/ast/stage_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/switch_statement.h"
#include "src/ast/type/alias_type.h"
@@ -1524,10 +1525,10 @@
if (has_error()) {
return false;
}
- if (deco == ast::StructDecoration::kNone) {
+ if (deco == nullptr) {
return true;
}
- decos.push_back(deco);
+ decos.emplace_back(std::move(deco));
next(); // Consume the peek of [[
next(); // Consume the peek from the struct_decoration
@@ -1543,11 +1544,11 @@
// struct_decoration
// : BLOCK
-ast::StructDecoration ParserImpl::struct_decoration(Token t) {
+std::unique_ptr<ast::StructDecoration> ParserImpl::struct_decoration(Token t) {
if (t.IsBlock()) {
- return ast::StructDecoration::kBlock;
+ return std::make_unique<ast::StructBlockDecoration>();
}
- return ast::StructDecoration::kNone;
+ return nullptr;
}
// struct_body_decl
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 467b6ee..4133f4b 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -189,7 +189,7 @@
/// Parses a `struct_decoration` grammar element
/// @param t the current token
/// @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
/// @returns the struct members
ast::StructMemberList struct_body_decl();
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc
index 3222117..c217341 100644
--- a/src/reader/wgsl/parser_impl_struct_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -51,7 +51,7 @@
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
EXPECT_EQ(s->impl()->members()[1]->name(), "b");
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) {
@@ -69,8 +69,8 @@
EXPECT_EQ(s->impl()->members()[0]->name(), "a");
EXPECT_EQ(s->impl()->members()[1]->name(), "b");
ASSERT_EQ(s->impl()->decorations().size(), 2u);
- EXPECT_EQ(s->impl()->decorations()[0], ast::StructDecoration::kBlock);
- EXPECT_EQ(s->impl()->decorations()[1], ast::StructDecoration::kBlock);
+ EXPECT_TRUE(s->impl()->decorations()[0]->IsBlock());
+ EXPECT_TRUE(s->impl()->decorations()[1]->IsBlock());
}
TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
index 5c0ef8e..3ff9674 100644
--- a/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decoration_decl_test.cc
@@ -27,7 +27,7 @@
ASSERT_TRUE(p->struct_decoration_decl(decos));
ASSERT_FALSE(p->has_error());
EXPECT_EQ(decos.size(), 1u);
- EXPECT_EQ(decos[0], ast::StructDecoration::kBlock);
+ EXPECT_TRUE(decos[0]->IsBlock());
}
TEST_F(ParserImplTest, StructDecorationDecl_MissingAttrRight) {
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
index 4d07af4..a8da5b2 100644
--- a/src/reader/wgsl/parser_impl_struct_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
@@ -24,7 +24,7 @@
struct StructDecorationData {
const char* input;
- ast::StructDecoration result;
+ bool is_block;
};
inline std::ostream& operator<<(std::ostream& out, StructDecorationData data) {
out << std::string(data.input);
@@ -40,17 +40,16 @@
auto deco = p->struct_decoration(p->peek());
ASSERT_FALSE(p->has_error());
- EXPECT_EQ(deco, params.result);
+ EXPECT_EQ(deco->IsBlock(), params.is_block);
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
StructDecorationTest,
- testing::Values(StructDecorationData{
- "block", ast::StructDecoration::kBlock}));
+ testing::Values(StructDecorationData{"block", true}));
TEST_F(ParserImplTest, StructDecoration_NoMatch) {
auto* p = parser("not-a-stage");
auto deco = p->struct_decoration(p->peek());
- ASSERT_EQ(deco, ast::StructDecoration::kNone);
+ ASSERT_EQ(deco, nullptr);
auto t = p->next();
EXPECT_TRUE(t.IsIdentifier());
diff --git a/src/transform/vertex_pulling_transform.cc b/src/transform/vertex_pulling_transform.cc
index 3ab074d..e8390d7 100644
--- a/src/transform/vertex_pulling_transform.cc
+++ b/src/transform/vertex_pulling_transform.cc
@@ -25,6 +25,7 @@
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@@ -234,7 +235,7 @@
kStructBufferName, internal_array_type, std::move(member_dec)));
ast::StructDecorationList decos;
- decos.push_back(ast::StructDecoration::kBlock);
+ decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto* struct_type =
ctx_->type_mgr().Get(std::make_unique<ast::type::StructType>(
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index 62c7bae..274a6be 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -14,6 +14,7 @@
#include "src/ast/module.h"
#include "src/ast/struct.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h"
@@ -286,7 +287,7 @@
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
ast::StructDecorationList decos;
- decos.push_back(ast::StructDecoration::kBlock);
+ decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
diff --git a/src/writer/msl/generator_impl_type_test.cc b/src/writer/msl/generator_impl_type_test.cc
index d49714e..c3a1205 100644
--- a/src/writer/msl/generator_impl_type_test.cc
+++ b/src/writer/msl/generator_impl_type_test.cc
@@ -15,6 +15,7 @@
#include "gtest/gtest.h"
#include "src/ast/module.h"
#include "src/ast/struct.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h"
@@ -324,7 +325,7 @@
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
ast::StructDecorationList decos;
- decos.push_back(ast::StructDecoration::kBlock);
+ decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members));
diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc
index fe8710e..aef87ed 100644
--- a/src/writer/spirv/builder_type_test.cc
+++ b/src/writer/spirv/builder_type_test.cc
@@ -18,6 +18,7 @@
#include "src/ast/identifier_expression.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/type/access_control_type.h"
@@ -361,7 +362,7 @@
std::make_unique<ast::StructMember>("a", &f32, std::move(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),
std::move(members));
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 205df74..50c378b 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -552,8 +552,10 @@
bool GeneratorImpl::EmitStructType(const ast::type::StructType* str) {
auto* impl = str->impl();
- for (auto deco : impl->decorations()) {
- out_ << "[[" << deco << "]]" << std::endl;
+ for (auto& deco : impl->decorations()) {
+ out_ << "[[";
+ deco->to_str(out_);
+ out_ << "]]" << std::endl;
}
out_ << "struct " << str->name() << " {" << std::endl;
diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc
index a8b5070..2fc6542 100644
--- a/src/writer/wgsl/generator_impl_type_test.cc
+++ b/src/writer/wgsl/generator_impl_type_test.cc
@@ -15,6 +15,7 @@
#include "gtest/gtest.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
+#include "src/ast/struct_block_decoration.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_decoration.h"
@@ -204,7 +205,7 @@
std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
ast::StructDecorationList decos;
- decos.push_back(ast::StructDecoration::kBlock);
+ decos.push_back(std::make_unique<ast::StructBlockDecoration>());
auto str =
std::make_unique<ast::Struct>(std::move(decos), std::move(members));