ast: Have all AST types derive from ast::Node

A common base class is required to move from std::unique_ptr<> to raw pointers for AST types.

Also unifies a bunch of similar APIs.

Bug: tint:322
Change-Id: If829f8c3f22069adf62751365f1f1eeb646aba08
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32660
Commit-Queue: Ben Clayton <bclayton@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/array_decoration.h b/src/ast/array_decoration.h
index 52d9407..1594e01 100644
--- a/src/ast/array_decoration.h
+++ b/src/ast/array_decoration.h
@@ -40,9 +40,6 @@
   /// @returns the decoration as a stride decoration
   StrideDecoration* AsStride();
 
-  /// @returns the decoration as a string
-  virtual std::string to_str() const = 0;
-
  protected:
   /// Constructor
   /// @param source the source of this decoration
diff --git a/src/ast/binding_decoration.cc b/src/ast/binding_decoration.cc
index bb237f0..64632a6 100644
--- a/src/ast/binding_decoration.cc
+++ b/src/ast/binding_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void BindingDecoration::to_str(std::ostream& out) const {
+void BindingDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "BindingDecoration{" << value_ << "}" << std::endl;
 }
 
diff --git a/src/ast/binding_decoration.h b/src/ast/binding_decoration.h
index 20fec89..b6633c2 100644
--- a/src/ast/binding_decoration.h
+++ b/src/ast/binding_decoration.h
@@ -38,8 +38,9 @@
   uint32_t value() const { return value_; }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t value_;
diff --git a/src/ast/binding_decoration_test.cc b/src/ast/binding_decoration_test.cc
index 26f91cf..2f463fe 100644
--- a/src/ast/binding_decoration_test.cc
+++ b/src/ast/binding_decoration_test.cc
@@ -39,7 +39,7 @@
 TEST_F(BindingDecorationTest, ToStr) {
   BindingDecoration d{2, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(BindingDecoration{2}
 )");
 }
diff --git a/src/ast/builtin_decoration.cc b/src/ast/builtin_decoration.cc
index 1ac7155..6dc0bbd 100644
--- a/src/ast/builtin_decoration.cc
+++ b/src/ast/builtin_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void BuiltinDecoration::to_str(std::ostream& out) const {
+void BuiltinDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "BuiltinDecoration{" << builtin_ << "}" << std::endl;
 }
 
diff --git a/src/ast/builtin_decoration.h b/src/ast/builtin_decoration.h
index 30b873c..b8169cb 100644
--- a/src/ast/builtin_decoration.h
+++ b/src/ast/builtin_decoration.h
@@ -37,8 +37,9 @@
   Builtin value() const { return builtin_; }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   Builtin builtin_ = Builtin::kNone;
diff --git a/src/ast/builtin_decoration_test.cc b/src/ast/builtin_decoration_test.cc
index 37bc260..ec1b6cc 100644
--- a/src/ast/builtin_decoration_test.cc
+++ b/src/ast/builtin_decoration_test.cc
@@ -39,7 +39,7 @@
 TEST_F(BuiltinDecorationTest, ToStr) {
   BuiltinDecoration d{Builtin::kFragDepth, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(BuiltinDecoration{frag_depth}
 )");
 }
diff --git a/src/ast/constant_id_decoration.cc b/src/ast/constant_id_decoration.cc
index 6afca22..9be39fd 100644
--- a/src/ast/constant_id_decoration.cc
+++ b/src/ast/constant_id_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void ConstantIdDecoration::to_str(std::ostream& out) const {
+void ConstantIdDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "ConstantIdDecoration{" << value_ << "}" << std::endl;
 }
 
diff --git a/src/ast/constant_id_decoration.h b/src/ast/constant_id_decoration.h
index 1bbaeb0..fbd8ba0 100644
--- a/src/ast/constant_id_decoration.h
+++ b/src/ast/constant_id_decoration.h
@@ -37,8 +37,9 @@
   uint32_t value() const { return value_; }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t value_ = 0;
diff --git a/src/ast/constant_id_decoration_test.cc b/src/ast/constant_id_decoration_test.cc
index 607ef75..93077eb 100644
--- a/src/ast/constant_id_decoration_test.cc
+++ b/src/ast/constant_id_decoration_test.cc
@@ -39,7 +39,7 @@
 TEST_F(ConstantIdDecorationTest, ToStr) {
   ConstantIdDecoration d{1200, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(ConstantIdDecoration{1200}
 )");
 }
diff --git a/src/ast/decorated_variable.cc b/src/ast/decorated_variable.cc
index 2b16b99..f0b621a 100644
--- a/src/ast/decorated_variable.cc
+++ b/src/ast/decorated_variable.cc
@@ -86,8 +86,7 @@
   make_indent(out, indent + 2);
   out << "Decorations{" << std::endl;
   for (const auto& deco : decorations_) {
-    make_indent(out, indent + 4);
-    deco->to_str(out);
+    deco->to_str(out, indent + 4);
   }
 
   make_indent(out, indent + 2);
diff --git a/src/ast/decoration.cc b/src/ast/decoration.cc
index c4abc90..1b17eb8 100644
--- a/src/ast/decoration.cc
+++ b/src/ast/decoration.cc
@@ -35,5 +35,9 @@
   return out << "<unknown>";
 }
 
+bool Decoration::IsValid() const {
+  return true;
+}
+
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/decoration.h b/src/ast/decoration.h
index 878c31e..ea6d686 100644
--- a/src/ast/decoration.h
+++ b/src/ast/decoration.h
@@ -19,6 +19,7 @@
 #include <ostream>
 #include <vector>
 
+#include "src/ast/node.h"
 #include "src/source.h"
 
 namespace tint {
@@ -36,9 +37,9 @@
 std::ostream& operator<<(std::ostream& out, DecorationKind data);
 
 /// The base class for all decorations
-class Decoration {
+class Decoration : public Node {
  public:
-  virtual ~Decoration();
+  ~Decoration() override;
 
   /// @return the decoration kind
   DecorationKind GetKind() const { return kind_; }
@@ -49,19 +50,18 @@
     return GetKind() == TO::Kind;
   }
 
-  /// @return the source of this decoration
-  const Source& GetSource() { return source_; }
+  /// @returns true if the node is valid
+  bool IsValid() const override;
 
  protected:
   /// Constructor
   /// @param kind represents the derived type
   /// @param source the source of this decoration
   Decoration(DecorationKind kind, const Source& source)
-      : kind_(kind), source_(source) {}
+      : Node(source), kind_(kind) {}
 
  private:
   DecorationKind const kind_;
-  Source const source_;
 };
 
 /// As dynamically casts |deco| to the target type |TO|.
diff --git a/src/ast/function.cc b/src/ast/function.cc
index d910290..ab1b735 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -233,8 +233,7 @@
       << std::endl;
 
   for (const auto& deco : decorations()) {
-    make_indent(out, indent);
-    deco->to_str(out);
+    deco->to_str(out, indent);
   }
 
   make_indent(out, indent);
diff --git a/src/ast/function_decoration.h b/src/ast/function_decoration.h
index 8112351..603cb49 100644
--- a/src/ast/function_decoration.h
+++ b/src/ast/function_decoration.h
@@ -45,10 +45,6 @@
   /// @returns the decoration as a workgroup decoration
   const WorkgroupDecoration* AsWorkgroup() const;
 
-  /// Outputs the function decoration to the given stream
-  /// @param out the stream to output too
-  virtual void to_str(std::ostream& out) const = 0;
-
  protected:
   /// Constructor
   /// @param source the source of this decoration
diff --git a/src/ast/literal.cc b/src/ast/literal.cc
index 3ac8543..35733c7 100644
--- a/src/ast/literal.cc
+++ b/src/ast/literal.cc
@@ -84,5 +84,14 @@
   return static_cast<UintLiteral*>(this);
 }
 
+bool Literal::IsValid() const {
+  return true;
+}
+
+void Literal::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
+  out << to_str();
+}
+
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/literal.h b/src/ast/literal.h
index c60f577..2154b2b 100644
--- a/src/ast/literal.h
+++ b/src/ast/literal.h
@@ -17,6 +17,7 @@
 
 #include <string>
 
+#include "src/ast/node.h"
 #include "src/ast/type/type.h"
 
 namespace tint {
@@ -30,9 +31,9 @@
 class UintLiteral;
 
 /// Base class for a literal value
-class Literal {
+class Literal : public Node {
  public:
-  virtual ~Literal();
+  ~Literal() override;
 
   /// @returns true if this is a bool literal
   virtual bool IsBool() const;
@@ -63,6 +64,14 @@
   /// @returns the type of the literal
   ast::type::Type* type() const { return type_; }
 
+  /// @returns true if the node is valid
+  bool IsValid() const override;
+
+  /// Writes a representation of the node to the output stream
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
+
   /// @returns the literal as a string
   virtual std::string to_str() const = 0;
 
diff --git a/src/ast/location_decoration.cc b/src/ast/location_decoration.cc
index 7e1db78..948fc8e 100644
--- a/src/ast/location_decoration.cc
+++ b/src/ast/location_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void LocationDecoration::to_str(std::ostream& out) const {
+void LocationDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "LocationDecoration{" << value_ << "}" << std::endl;
 }
 
diff --git a/src/ast/location_decoration.h b/src/ast/location_decoration.h
index 2e74fd7..d5474da 100644
--- a/src/ast/location_decoration.h
+++ b/src/ast/location_decoration.h
@@ -38,8 +38,9 @@
   uint32_t value() const { return value_; }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t value_;
diff --git a/src/ast/location_decoration_test.cc b/src/ast/location_decoration_test.cc
index 900d96c..e09f2eb 100644
--- a/src/ast/location_decoration_test.cc
+++ b/src/ast/location_decoration_test.cc
@@ -41,7 +41,7 @@
 TEST_F(LocationDecorationTest, ToStr) {
   LocationDecoration d{2, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(LocationDecoration{2}
 )");
 }
diff --git a/src/ast/set_decoration.cc b/src/ast/set_decoration.cc
index 1a89ac9..08d5312 100644
--- a/src/ast/set_decoration.cc
+++ b/src/ast/set_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void SetDecoration::to_str(std::ostream& out) const {
+void SetDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "SetDecoration{" << value_ << "}" << std::endl;
 }
 
diff --git a/src/ast/set_decoration.h b/src/ast/set_decoration.h
index e76795d..5398c88 100644
--- a/src/ast/set_decoration.h
+++ b/src/ast/set_decoration.h
@@ -38,8 +38,9 @@
   uint32_t value() const { return value_; }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t value_;
diff --git a/src/ast/set_decoration_test.cc b/src/ast/set_decoration_test.cc
index 5dc88cb..e0782b1 100644
--- a/src/ast/set_decoration_test.cc
+++ b/src/ast/set_decoration_test.cc
@@ -39,7 +39,7 @@
 TEST_F(SetDecorationTest, ToStr) {
   SetDecoration d{2, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(SetDecoration{2}
 )");
 }
diff --git a/src/ast/stage_decoration.cc b/src/ast/stage_decoration.cc
index e10b48d..838042d 100644
--- a/src/ast/stage_decoration.cc
+++ b/src/ast/stage_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void StageDecoration::to_str(std::ostream& out) const {
+void StageDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "StageDecoration{" << stage_ << "}" << std::endl;
 }
 
diff --git a/src/ast/stage_decoration.h b/src/ast/stage_decoration.h
index 3f24ed7..188170b 100644
--- a/src/ast/stage_decoration.h
+++ b/src/ast/stage_decoration.h
@@ -37,8 +37,9 @@
   ast::PipelineStage value() const { return stage_; }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   ast::PipelineStage stage_ = ast::PipelineStage::kNone;
diff --git a/src/ast/stage_decoration_test.cc b/src/ast/stage_decoration_test.cc
index b447313..19729c0 100644
--- a/src/ast/stage_decoration_test.cc
+++ b/src/ast/stage_decoration_test.cc
@@ -38,7 +38,7 @@
 TEST_F(StageDecorationTest, ToStr) {
   StageDecoration d{ast::PipelineStage::kFragment, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(StageDecoration{fragment}
 )");
 }
diff --git a/src/ast/stride_decoration.cc b/src/ast/stride_decoration.cc
index 77a0672..879fd5d 100644
--- a/src/ast/stride_decoration.cc
+++ b/src/ast/stride_decoration.cc
@@ -26,8 +26,9 @@
 
 StrideDecoration::~StrideDecoration() = default;
 
-std::string StrideDecoration::to_str() const {
-  return "stride " + std::to_string(stride_);
+void StrideDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
+  out << "stride " << stride_;
 }
 
 }  // namespace ast
diff --git a/src/ast/stride_decoration.h b/src/ast/stride_decoration.h
index c75ec25..f6ee3ff 100644
--- a/src/ast/stride_decoration.h
+++ b/src/ast/stride_decoration.h
@@ -39,8 +39,10 @@
   /// @returns the stride value
   uint32_t stride() const { return stride_; }
 
-  /// @returns the decoration as a string
-  std::string to_str() const override;
+  /// Outputs the decoration to the given stream
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t stride_;
diff --git a/src/ast/stride_decoration_test.cc b/src/ast/stride_decoration_test.cc
index 076802d..ac378e8 100644
--- a/src/ast/stride_decoration_test.cc
+++ b/src/ast/stride_decoration_test.cc
@@ -35,10 +35,10 @@
 TEST_F(StrideDecorationTest, Source) {
   StrideDecoration d{
       2, Source{Source::Range{Source::Location{1, 2}, Source::Location{3, 4}}}};
-  EXPECT_EQ(d.GetSource().range.begin.line, 1u);
-  EXPECT_EQ(d.GetSource().range.begin.column, 2u);
-  EXPECT_EQ(d.GetSource().range.end.line, 3u);
-  EXPECT_EQ(d.GetSource().range.end.column, 4u);
+  EXPECT_EQ(d.source().range.begin.line, 1u);
+  EXPECT_EQ(d.source().range.begin.column, 2u);
+  EXPECT_EQ(d.source().range.end.line, 3u);
+  EXPECT_EQ(d.source().range.end.column, 4u);
 }
 
 }  // namespace
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index 8f1e23b..c15c0d1 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -73,7 +73,7 @@
   for (auto& deco : decorations_) {
     make_indent(out, indent + 2);
     out << "[[";
-    deco->to_str(out);
+    deco->to_str(out, 0);
     out << "]]" << std::endl;
   }
   for (const auto& member : members_) {
diff --git a/src/ast/struct_block_decoration.cc b/src/ast/struct_block_decoration.cc
index 4d156cf..585646d 100644
--- a/src/ast/struct_block_decoration.cc
+++ b/src/ast/struct_block_decoration.cc
@@ -26,7 +26,8 @@
   return true;
 }
 
-void StructBlockDecoration::to_str(std::ostream& out) const {
+void StructBlockDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "block";
 }
 
diff --git a/src/ast/struct_block_decoration.h b/src/ast/struct_block_decoration.h
index 55cd3d4..f9ae0ab 100644
--- a/src/ast/struct_block_decoration.h
+++ b/src/ast/struct_block_decoration.h
@@ -36,8 +36,9 @@
   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;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 };
 
 /// List of struct decorations
diff --git a/src/ast/struct_decoration.h b/src/ast/struct_decoration.h
index ba9f8d4..978d37e 100644
--- a/src/ast/struct_decoration.h
+++ b/src/ast/struct_decoration.h
@@ -35,10 +35,6 @@
   /// @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
   /// @param source the source of this decoration
diff --git a/src/ast/struct_member.cc b/src/ast/struct_member.cc
index 447fed9..1f735e0 100644
--- a/src/ast/struct_member.cc
+++ b/src/ast/struct_member.cc
@@ -75,7 +75,7 @@
   if (decorations_.size() > 0) {
     out << "[[ ";
     for (const auto& deco : decorations_)
-      out << deco->to_str() << " ";
+      out << deco->str() << " ";
     out << "]] ";
   }
 
diff --git a/src/ast/struct_member_decoration.h b/src/ast/struct_member_decoration.h
index a6c1c74..1e11aca 100644
--- a/src/ast/struct_member_decoration.h
+++ b/src/ast/struct_member_decoration.h
@@ -40,9 +40,6 @@
   /// @returns the decoration as an offset decoration
   StructMemberOffsetDecoration* AsOffset();
 
-  /// @returns the decoration as a string
-  virtual std::string to_str() const = 0;
-
  protected:
   /// Constructor
   /// @param source the source of this decoration
diff --git a/src/ast/struct_member_offset_decoration.cc b/src/ast/struct_member_offset_decoration.cc
index 98b3ca8..b3dec36 100644
--- a/src/ast/struct_member_offset_decoration.cc
+++ b/src/ast/struct_member_offset_decoration.cc
@@ -27,8 +27,10 @@
 
 StructMemberOffsetDecoration::~StructMemberOffsetDecoration() = default;
 
-std::string StructMemberOffsetDecoration::to_str() const {
-  return "offset " + std::to_string(offset_);
+void StructMemberOffsetDecoration::to_str(std::ostream& out,
+                                          size_t indent) const {
+  make_indent(out, indent);
+  out << "offset " << std::to_string(offset_);
 }
 
 }  // namespace ast
diff --git a/src/ast/struct_member_offset_decoration.h b/src/ast/struct_member_offset_decoration.h
index 3ca6b86..8e679fb 100644
--- a/src/ast/struct_member_offset_decoration.h
+++ b/src/ast/struct_member_offset_decoration.h
@@ -39,8 +39,10 @@
   /// @returns the offset value
   uint32_t offset() const { return offset_; }
 
-  /// @returns the decoration as a string
-  std::string to_str() const override;
+  /// Outputs the decoration to the given stream
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t offset_;
diff --git a/src/ast/variable_decoration.h b/src/ast/variable_decoration.h
index 4cb931b..16c0744 100644
--- a/src/ast/variable_decoration.h
+++ b/src/ast/variable_decoration.h
@@ -61,10 +61,6 @@
   /// @returns the decoration as a set decoration
   SetDecoration* AsSet();
 
-  /// Outputs the variable decoration to the given stream
-  /// @param out the stream to output too
-  virtual void to_str(std::ostream& out) const = 0;
-
  protected:
   /// Constructor
   /// @param source the source of this decoration
diff --git a/src/ast/workgroup_decoration.cc b/src/ast/workgroup_decoration.cc
index 1e3b107..7f6b38c 100644
--- a/src/ast/workgroup_decoration.cc
+++ b/src/ast/workgroup_decoration.cc
@@ -37,7 +37,8 @@
   return true;
 }
 
-void WorkgroupDecoration::to_str(std::ostream& out) const {
+void WorkgroupDecoration::to_str(std::ostream& out, size_t indent) const {
+  make_indent(out, indent);
   out << "WorkgroupDecoration{" << x_ << " " << y_ << " " << z_ << "}"
       << std::endl;
 }
diff --git a/src/ast/workgroup_decoration.h b/src/ast/workgroup_decoration.h
index 40574fe..d5e6226 100644
--- a/src/ast/workgroup_decoration.h
+++ b/src/ast/workgroup_decoration.h
@@ -53,8 +53,9 @@
   }
 
   /// Outputs the decoration to the given stream
-  /// @param out the stream to output too
-  void to_str(std::ostream& out) const override;
+  /// @param out the stream to write to
+  /// @param indent number of spaces to indent the node when writing
+  void to_str(std::ostream& out, size_t indent) const override;
 
  private:
   uint32_t x_ = 1;
diff --git a/src/ast/workgroup_decoration_test.cc b/src/ast/workgroup_decoration_test.cc
index 90c267d..edcbe6e 100644
--- a/src/ast/workgroup_decoration_test.cc
+++ b/src/ast/workgroup_decoration_test.cc
@@ -65,7 +65,7 @@
 TEST_F(WorkgroupDecorationTest, ToStr) {
   WorkgroupDecoration d{2, 4, 6, Source{}};
   std::ostringstream out;
-  d.to_str(out);
+  d.to_str(out, 0);
   EXPECT_EQ(out.str(), R"(WorkgroupDecoration{2 4 6}
 )");
 }
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 537c05c..d3c357b 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2844,7 +2844,7 @@
       std::stringstream msg;
       msg << deco->GetKind() << " decoration type cannot be used for "
           << T::Kind;
-      add_error(deco->GetSource(), msg.str());
+      add_error(deco->source(), msg.str());
       ok = false;
       continue;
     }
@@ -2864,7 +2864,7 @@
   if (in.empty()) {
     return true;
   }
-  add_error(in[0]->GetSource(), "unexpected decorations");
+  add_error(in[0]->source(), "unexpected decorations");
   return false;
 }
 
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index e07b6a6..38c2f48 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -1856,7 +1856,7 @@
         }
         current_offset = offset;
       } else {
-        error_ = "unsupported member decoration: " + deco->to_str();
+        error_ = "unsupported member decoration: " + deco->str();
         return false;
       }
     }
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index ddf0717..9880ee0 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -573,7 +573,7 @@
   auto* impl = str->impl();
   for (auto& deco : impl->decorations()) {
     out_ << "[[";
-    deco->to_str(out_);
+    deco->to_str(out_, 0);
     out_ << "]]" << std::endl;
   }
   out_ << "struct " << str->name() << " {" << std::endl;