ast/function: Remove [set|add]_decorations()

Move them to the constructor

Bug: tint:390
Change-Id: I30bb6a1de060b790bf5202194d020d4e3889a307
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35008
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/function.cc b/src/ast/function.cc
index 86a4f30..cdf622a 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -30,26 +30,18 @@
 namespace tint {
 namespace ast {
 
-Function::Function(const std::string& name,
-                   VariableList params,
-                   type::Type* return_type,
-                   BlockStatement* body)
-    : Base(),
-      name_(name),
-      params_(std::move(params)),
-      return_type_(return_type),
-      body_(body) {}
-
 Function::Function(const Source& source,
                    const std::string& name,
                    VariableList params,
                    type::Type* return_type,
-                   BlockStatement* body)
+                   BlockStatement* body,
+                   FunctionDecorationList decorations)
     : Base(source),
       name_(name),
       params_(std::move(params)),
       return_type_(return_type),
-      body_(body) {}
+      body_(body),
+      decorations_(std::move(decorations)) {}
 
 Function::Function(Function&&) = default;
 
@@ -217,11 +209,9 @@
 }
 
 Function* Function::Clone(CloneContext* ctx) const {
-  auto* cloned = ctx->mod->create<Function>(
+  return ctx->mod->create<Function>(
       ctx->Clone(source()), name_, ctx->Clone(params_),
-      ctx->Clone(return_type_), ctx->Clone(body_));
-  cloned->set_decorations(ctx->Clone(decorations_));
-  return cloned;
+      ctx->Clone(return_type_), ctx->Clone(body_), ctx->Clone(decorations_));
 }
 
 bool Function::IsValid() const {
diff --git a/src/ast/function.h b/src/ast/function.h
index e4bf327..ba819ab 100644
--- a/src/ast/function.h
+++ b/src/ast/function.h
@@ -51,25 +51,18 @@
   };
 
   /// Create a function
-  /// @param name the function name
-  /// @param params the function parameters
-  /// @param return_type the return type
-  /// @param body the function body
-  Function(const std::string& name,
-           VariableList params,
-           type::Type* return_type,
-           BlockStatement* body);
-  /// Create a function
   /// @param source the variable source
   /// @param name the function name
   /// @param params the function parameters
   /// @param return_type the return type
   /// @param body the function body
+  /// @param decorations the function decorations
   Function(const Source& source,
            const std::string& name,
            VariableList params,
            type::Type* return_type,
-           BlockStatement* body);
+           BlockStatement* body,
+           FunctionDecorationList decorations);
   /// Move constructor
   Function(Function&&);
 
@@ -80,17 +73,6 @@
   /// @returns the function params
   const VariableList& params() const { return params_; }
 
-  /// Sets the function decorations
-  /// @param decos the decorations to set. This will overwrite any existing
-  /// decorations
-  void set_decorations(FunctionDecorationList decos) {
-    decorations_ = std::move(decos);
-  }
-  /// Adds a decoration to the function
-  /// @param deco the decoration to set
-  void add_decoration(FunctionDecoration* deco) {
-    decorations_.push_back(deco);
-  }
   /// @returns the decorations attached to this function
   const FunctionDecorationList& decorations() const { return decorations_; }
 
diff --git a/src/ast/function_test.cc b/src/ast/function_test.cc
index c307284..08b0e44 100644
--- a/src/ast/function_test.cc
+++ b/src/ast/function_test.cc
@@ -40,7 +40,8 @@
   params.push_back(create<Variable>("var", StorageClass::kNone, &i32));
   auto* var = params[0];
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_EQ(f.name(), "func");
   ASSERT_EQ(f.params().size(), 1u);
   EXPECT_EQ(f.return_type(), &void_type);
@@ -55,7 +56,7 @@
   params.push_back(create<Variable>("var", StorageClass::kNone, &i32));
 
   Function f(Source{Source::Location{20, 2}}, "func", params, &void_type,
-             create<BlockStatement>());
+             create<BlockStatement>(), FunctionDecorationList{});
   auto src = f.source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
@@ -66,7 +67,8 @@
   type::I32 i32;
 
   Variable v("var", StorageClass::kInput, &i32);
-  Function f("func", VariableList{}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", VariableList{}, &void_type,
+             create<BlockStatement>(), FunctionDecorationList{});
 
   f.add_referenced_module_variable(&v);
   ASSERT_EQ(f.referenced_module_variables().size(), 1u);
@@ -101,7 +103,8 @@
   builtin2.set_decorations(
       {create<BuiltinDecoration>(Builtin::kFragDepth, Source{})});
 
-  Function f("func", VariableList{}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", VariableList{}, &void_type,
+             create<BlockStatement>(), FunctionDecorationList{});
 
   f.add_referenced_module_variable(&loc1);
   f.add_referenced_module_variable(&builtin1);
@@ -137,7 +140,8 @@
   builtin2.set_decorations(
       {create<BuiltinDecoration>(Builtin::kFragDepth, Source{})});
 
-  Function f("func", VariableList{}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", VariableList{}, &void_type,
+             create<BlockStatement>(), FunctionDecorationList{});
 
   f.add_referenced_module_variable(&loc1);
   f.add_referenced_module_variable(&builtin1);
@@ -155,7 +159,8 @@
 
 TEST_F(FunctionTest, AddDuplicateEntryPoints) {
   type::Void void_type;
-  Function f("func", VariableList{}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", VariableList{}, &void_type,
+             create<BlockStatement>(), FunctionDecorationList{});
 
   f.add_ancestor_entry_point("main");
   ASSERT_EQ(1u, f.ancestor_entry_points().size());
@@ -176,7 +181,8 @@
   auto* block = create<BlockStatement>();
   block->append(create<DiscardStatement>());
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(block);
   EXPECT_TRUE(f.IsValid());
 }
@@ -188,7 +194,8 @@
   VariableList params;
   params.push_back(create<Variable>("var", StorageClass::kNone, &i32));
 
-  Function f("", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_FALSE(f.IsValid());
 }
 
@@ -198,7 +205,8 @@
   VariableList params;
   params.push_back(create<Variable>("var", StorageClass::kNone, &i32));
 
-  Function f("func", params, nullptr, create<BlockStatement>());
+  Function f(Source{}, "func", params, nullptr, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_FALSE(f.IsValid());
 }
 
@@ -210,7 +218,8 @@
   params.push_back(create<Variable>("var", StorageClass::kNone, &i32));
   params.push_back(nullptr);
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_FALSE(f.IsValid());
 }
 
@@ -220,7 +229,8 @@
   VariableList params;
   params.push_back(create<Variable>("var", StorageClass::kNone, nullptr));
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_FALSE(f.IsValid());
 }
 
@@ -235,7 +245,8 @@
   block->append(create<DiscardStatement>());
   block->append(nullptr);
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(block);
   EXPECT_FALSE(f.IsValid());
 }
@@ -251,7 +262,8 @@
   block->append(create<DiscardStatement>());
   block->append(nullptr);
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(block);
   EXPECT_FALSE(f.IsValid());
 }
@@ -263,7 +275,8 @@
   auto* block = create<BlockStatement>();
   block->append(create<DiscardStatement>());
 
-  Function f("func", {}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", {}, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(block);
 
   std::ostringstream out;
@@ -283,9 +296,9 @@
   auto* block = create<BlockStatement>();
   block->append(create<DiscardStatement>());
 
-  Function f("func", {}, &void_type, create<BlockStatement>());
-  f.set_body(block);
-  f.add_decoration(create<WorkgroupDecoration>(2, 4, 6, Source{}));
+  Function f(
+      Source{}, "func", {}, &void_type, block,
+      FunctionDecorationList{create<WorkgroupDecoration>(2, 4, 6, Source{})});
 
   std::ostringstream out;
   f.to_str(out, 2);
@@ -308,7 +321,8 @@
   auto* block = create<BlockStatement>();
   block->append(create<DiscardStatement>());
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(block);
 
   std::ostringstream out;
@@ -330,7 +344,8 @@
 TEST_F(FunctionTest, TypeName) {
   type::Void void_type;
 
-  Function f("func", {}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", {}, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_EQ(f.type_name(), "__func__void");
 }
 
@@ -343,7 +358,8 @@
   params.push_back(create<Variable>("var1", StorageClass::kNone, &i32));
   params.push_back(create<Variable>("var2", StorageClass::kNone, &f32));
 
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   EXPECT_EQ(f.type_name(), "__func__void__i32__f32");
 }
 
@@ -354,7 +370,8 @@
   auto* body = create<BlockStatement>();
   auto* stmt = create<DiscardStatement>();
   body->append(stmt);
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(body);
 
   EXPECT_EQ(f.get_last_statement(), stmt);
@@ -365,7 +382,8 @@
 
   VariableList params;
   auto* body = create<BlockStatement>();
-  Function f("func", params, &void_type, create<BlockStatement>());
+  Function f(Source{}, "func", params, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   f.set_body(body);
 
   EXPECT_EQ(f.get_last_statement(), nullptr);
@@ -373,7 +391,8 @@
 
 TEST_F(FunctionTest, WorkgroupSize_NoneSet) {
   type::Void void_type;
-  Function f("f", {}, &void_type, create<BlockStatement>());
+  Function f(Source{}, "f", {}, &void_type, create<BlockStatement>(),
+             FunctionDecorationList{});
   uint32_t x = 0;
   uint32_t y = 0;
   uint32_t z = 0;
@@ -385,8 +404,8 @@
 
 TEST_F(FunctionTest, WorkgroupSize) {
   type::Void void_type;
-  Function f("f", {}, &void_type, create<BlockStatement>());
-  f.add_decoration(create<WorkgroupDecoration>(2u, 4u, 6u, Source{}));
+  Function f(Source{}, "f", {}, &void_type, create<BlockStatement>(),
+             {create<WorkgroupDecoration>(2u, 4u, 6u, Source{})});
 
   uint32_t x = 0;
   uint32_t y = 0;
diff --git a/src/ast/module_test.cc b/src/ast/module_test.cc
index a26b62b..c5ff933 100644
--- a/src/ast/module_test.cc
+++ b/src/ast/module_test.cc
@@ -49,7 +49,8 @@
   Module m;
 
   auto* func =
-      create<Function>("main", VariableList{}, &f32, create<BlockStatement>());
+      create<Function>(Source{}, "main", VariableList{}, &f32,
+                       create<BlockStatement>(), ast::FunctionDecorationList{});
   m.AddFunction(func);
   EXPECT_EQ(func, m.FindFunctionByName("main"));
 }
@@ -125,7 +126,8 @@
 TEST_F(ModuleTest, IsValid_Function) {
   type::F32 f32;
   auto* func =
-      create<Function>("main", VariableList(), &f32, create<BlockStatement>());
+      create<Function>(Source{}, "main", VariableList(), &f32,
+                       create<BlockStatement>(), ast::FunctionDecorationList{});
 
   Module m;
   m.AddFunction(func);
@@ -140,7 +142,8 @@
 
 TEST_F(ModuleTest, IsValid_Invalid_Function) {
   VariableList p;
-  auto* func = create<Function>("", p, nullptr, nullptr);
+  auto* func = create<Function>(Source{}, "", p, nullptr, nullptr,
+                                ast::FunctionDecorationList{});
 
   Module m;
   m.AddFunction(func);
diff --git a/src/inspector/inspector_test.cc b/src/inspector/inspector_test.cc
index 34c8796..50d9d1f 100644
--- a/src/inspector/inspector_test.cc
+++ b/src/inspector/inspector_test.cc
@@ -76,27 +76,34 @@
 
   /// Generates an empty function
   /// @param name name of the function created
+  /// @param decorations the function decorations
   /// @returns a function object
-  ast::Function* MakeEmptyBodyFunction(std::string name) {
+  ast::Function* MakeEmptyBodyFunction(
+      std::string name,
+      ast::FunctionDecorationList decorations = {}) {
     auto* body = create<ast::BlockStatement>();
     body->append(create<ast::ReturnStatement>());
-    return create<ast::Function>(name, ast::VariableList(), void_type(), body);
+    return create<ast::Function>(Source{}, name, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Generates a function that calls another
   /// @param caller name of the function created
   /// @param callee name of the function to be called
+  /// @param decorations the function decorations
   /// @returns a function object
-  ast::Function* MakeCallerBodyFunction(std::string caller,
-                                        std::string callee) {
+  ast::Function* MakeCallerBodyFunction(
+      std::string caller,
+      std::string callee,
+      ast::FunctionDecorationList decorations = {}) {
     auto* body = create<ast::BlockStatement>();
     auto* ident_expr = create<ast::IdentifierExpression>(callee);
     auto* call_expr =
         create<ast::CallExpression>(ident_expr, ast::ExpressionList());
     body->append(create<ast::CallStatement>(call_expr));
     body->append(create<ast::ReturnStatement>());
-    return create<ast::Function>(caller, ast::VariableList(), void_type(),
-                                 body);
+    return create<ast::Function>(Source{}, caller, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Add In/Out variables to the global variables
@@ -120,10 +127,12 @@
   /// @param name name of the function created
   /// @param inout_vars tuples of {in, out} that will be converted into out = in
   ///                   calls in the function body
+  /// @param decorations the function decorations
   /// @returns a function object
   ast::Function* MakeInOutVariableBodyFunction(
       std::string name,
-      std::vector<std::tuple<std::string, std::string>> inout_vars) {
+      std::vector<std::tuple<std::string, std::string>> inout_vars,
+      ast::FunctionDecorationList decorations = {}) {
     auto* body = create<ast::BlockStatement>();
     for (auto inout : inout_vars) {
       std::string in, out;
@@ -133,7 +142,8 @@
           create<ast::IdentifierExpression>(in)));
     }
     body->append(create<ast::ReturnStatement>());
-    return create<ast::Function>(name, ast::VariableList(), void_type(), body);
+    return create<ast::Function>(Source{}, name, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Generates a function that references in/out variables and calls another
@@ -142,11 +152,13 @@
   /// @param callee name of the function to be called
   /// @param inout_vars tuples of {in, out} that will be converted into out = in
   ///                   calls in the function body
+  /// @param decorations the function decorations
   /// @returns a function object
   ast::Function* MakeInOutVariableCallerBodyFunction(
       std::string caller,
       std::string callee,
-      std::vector<std::tuple<std::string, std::string>> inout_vars) {
+      std::vector<std::tuple<std::string, std::string>> inout_vars,
+      ast::FunctionDecorationList decorations = {}) {
     auto* body = create<ast::BlockStatement>();
     for (auto inout : inout_vars) {
       std::string in, out;
@@ -160,8 +172,8 @@
         create<ast::CallExpression>(ident_expr, ast::ExpressionList());
     body->append(create<ast::CallStatement>(call_expr));
     body->append(create<ast::ReturnStatement>());
-    return create<ast::Function>(caller, ast::VariableList(), void_type(),
-                                 body);
+    return create<ast::Function>(Source{}, caller, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Add a Constant ID to the global variables.
@@ -404,8 +416,9 @@
     }
 
     body->append(create<ast::ReturnStatement>());
-    return create<ast::Function>(func_name, ast::VariableList(), void_type(),
-                                 body);
+    return create<ast::Function>(Source{}, func_name, ast::VariableList(),
+                                 void_type(), body,
+                                 ast::FunctionDecorationList{});
   }
 
   /// Adds a regular sampler variable to the module
@@ -498,13 +511,16 @@
   /// @param texture_name name of the texture to be sampled
   /// @param sampler_name name of the sampler to use
   /// @param coords_name name of the coords variable to use
+  /// @param base_type sampler base type
+  /// @param decorations the function decorations
   /// @returns a function that references all of the values specified
   ast::Function* MakeSamplerReferenceBodyFunction(
       const std::string& func_name,
       const std::string& texture_name,
       const std::string& sampler_name,
       const std::string& coords_name,
-      ast::type::Type* base_type) {
+      ast::type::Type* base_type,
+      ast::FunctionDecorationList decorations = {}) {
     std::string result_name = "sampler_result";
 
     auto* body = create<ast::BlockStatement>();
@@ -524,8 +540,8 @@
         create<ast::IdentifierExpression>("sampler_result"), call_expr));
     body->append(create<ast::ReturnStatement>());
 
-    return create<ast::Function>(func_name, ast::VariableList(), void_type(),
-                                 body);
+    return create<ast::Function>(Source{}, func_name, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Generates a function that references a specific sampler variable
@@ -534,6 +550,8 @@
   /// @param sampler_name name of the sampler to use
   /// @param coords_name name of the coords variable to use
   /// @param array_index name of the array index variable to use
+  /// @param base_type sampler base type
+  /// @param decorations the function decorations
   /// @returns a function that references all of the values specified
   ast::Function* MakeSamplerReferenceBodyFunction(
       const std::string& func_name,
@@ -541,7 +559,8 @@
       const std::string& sampler_name,
       const std::string& coords_name,
       const std::string& array_index,
-      ast::type::Type* base_type) {
+      ast::type::Type* base_type,
+      ast::FunctionDecorationList decorations = {}) {
     std::string result_name = "sampler_result";
 
     auto* body = create<ast::BlockStatement>();
@@ -562,8 +581,8 @@
         create<ast::IdentifierExpression>("sampler_result"), call_expr));
     body->append(create<ast::ReturnStatement>());
 
-    return create<ast::Function>(func_name, ast::VariableList(), void_type(),
-                                 body);
+    return create<ast::Function>(Source{}, func_name, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Generates a function that references a specific comparison sampler
@@ -573,6 +592,8 @@
   /// @param sampler_name name of the sampler to use
   /// @param coords_name name of the coords variable to use
   /// @param depth_name name of the depth reference to use
+  /// @param base_type sampler base type
+  /// @param decorations the function decorations
   /// @returns a function that references all of the values specified
   ast::Function* MakeComparisonSamplerReferenceBodyFunction(
       const std::string& func_name,
@@ -580,7 +601,8 @@
       const std::string& sampler_name,
       const std::string& coords_name,
       const std::string& depth_name,
-      ast::type::Type* base_type) {
+      ast::type::Type* base_type,
+      ast::FunctionDecorationList decorations = {}) {
     std::string result_name = "sampler_result";
 
     auto* body = create<ast::BlockStatement>();
@@ -601,8 +623,8 @@
         create<ast::IdentifierExpression>("sampler_result"), call_expr));
     body->append(create<ast::ReturnStatement>());
 
-    return create<ast::Function>(func_name, ast::VariableList(), void_type(),
-                                 body);
+    return create<ast::Function>(Source{}, func_name, ast::VariableList(),
+                                 void_type(), body, decorations);
   }
 
   /// Gets an appropriate type for the data in a given texture type.
@@ -764,9 +786,11 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, OneEntryPoint) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   // TODO(dsinclair): Update to run the namer transform when available.
@@ -781,14 +805,18 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, MultipleEntryPoints) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
-  auto* bar = MakeEmptyBodyFunction("bar");
-  bar->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* bar = MakeEmptyBodyFunction(
+      "bar",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
   mod()->AddFunction(bar);
 
   // TODO(dsinclair): Update to run the namer transform when available.
@@ -809,14 +837,18 @@
   auto* func = MakeEmptyBodyFunction("func");
   mod()->AddFunction(func);
 
-  auto* foo = MakeCallerBodyFunction("foo", "func");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeCallerBodyFunction(
+      "foo", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
-  auto* bar = MakeCallerBodyFunction("bar", "func");
-  bar->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* bar = MakeCallerBodyFunction(
+      "bar", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
   mod()->AddFunction(bar);
 
   // TODO(dsinclair): Update to run the namer transform when available.
@@ -834,9 +866,11 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, DefaultWorkgroupSize) {
-  auto* foo = MakeCallerBodyFunction("foo", "func");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeCallerBodyFunction(
+      "foo", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   auto result = inspector()->GetEntryPoints();
@@ -851,10 +885,12 @@
 }
 
 TEST_F(InspectorGetEntryPointTest, NonDefaultWorkgroupSize) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
-  foo->add_decoration(create<ast::WorkgroupDecoration>(8u, 2u, 1u, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+          create<ast::WorkgroupDecoration>(8u, 2u, 1u, Source{}),
+      });
   mod()->AddFunction(foo);
 
   auto result = inspector()->GetEntryPoints();
@@ -872,9 +908,11 @@
   auto* func = MakeEmptyBodyFunction("func");
   mod()->AddFunction(func);
 
-  auto* foo = MakeCallerBodyFunction("foo", "func");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeCallerBodyFunction(
+      "foo", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   auto result = inspector()->GetEntryPoints();
@@ -888,9 +926,11 @@
 TEST_F(InspectorGetEntryPointTest, EntryPointInOutVariables) {
   AddInOutVariables({{"in_var", "out_var"}});
 
-  auto* foo = MakeInOutVariableBodyFunction("foo", {{"in_var", "out_var"}});
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeInOutVariableBodyFunction(
+      "foo", {{"in_var", "out_var"}},
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -912,9 +952,11 @@
   auto* func = MakeInOutVariableBodyFunction("func", {{"in_var", "out_var"}});
   mod()->AddFunction(func);
 
-  auto* foo = MakeCallerBodyFunction("foo", "func");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeCallerBodyFunction(
+      "foo", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -936,10 +978,11 @@
   auto* func = MakeInOutVariableBodyFunction("func", {{"in_var", "out_var"}});
   mod()->AddFunction(func);
 
-  auto* foo = MakeInOutVariableCallerBodyFunction("foo", "func",
-                                                  {{"in_var", "out_var"}});
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeInOutVariableCallerBodyFunction(
+      "foo", "func", {{"in_var", "out_var"}},
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -959,9 +1002,10 @@
   AddInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
 
   auto* foo = MakeInOutVariableBodyFunction(
-      "foo", {{"in_var", "out_var"}, {"in2_var", "out2_var"}});
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "foo", {{"in_var", "out_var"}, {"in2_var", "out2_var"}},
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -986,9 +1030,11 @@
       "func", {{"in_var", "out_var"}, {"in2_var", "out2_var"}});
   mod()->AddFunction(func);
 
-  auto* foo = MakeCallerBodyFunction("foo", "func");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeCallerBodyFunction(
+      "foo", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1009,14 +1055,18 @@
 TEST_F(InspectorGetEntryPointTest, MultipleEntryPointsInOutVariables) {
   AddInOutVariables({{"in_var", "out_var"}, {"in2_var", "out2_var"}});
 
-  auto* foo = MakeInOutVariableBodyFunction("foo", {{"in_var", "out2_var"}});
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeInOutVariableBodyFunction(
+      "foo", {{"in_var", "out2_var"}},
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
-  auto* bar = MakeInOutVariableBodyFunction("bar", {{"in2_var", "out_var"}});
-  bar->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* bar = MakeInOutVariableBodyFunction(
+      "bar", {{"in2_var", "out_var"}},
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
   mod()->AddFunction(bar);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1049,15 +1099,18 @@
   auto* func = MakeInOutVariableBodyFunction("func", {{"in2_var", "out2_var"}});
   mod()->AddFunction(func);
 
-  auto* foo = MakeInOutVariableCallerBodyFunction("foo", "func",
-                                                  {{"in_var", "out_var"}});
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeInOutVariableCallerBodyFunction(
+      "foo", "func", {{"in_var", "out_var"}},
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
-  auto* bar = MakeCallerBodyFunction("bar", "func");
-  bar->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* bar = MakeCallerBodyFunction(
+      "bar", "func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
   mod()->AddFunction(bar);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1109,9 +1162,11 @@
 // TODO(rharrison): Reenable once GetRemappedNameForEntryPoint isn't a pass
 // through
 TEST_F(InspectorGetRemappedNameForEntryPointTest, DISABLED_OneEntryPoint) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   // TODO(dsinclair): Update to run the namer transform when available.
@@ -1126,16 +1181,20 @@
 // through
 TEST_F(InspectorGetRemappedNameForEntryPointTest,
        DISABLED_MultipleEntryPoints) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   // TODO(dsinclair): Update to run the namer transform when available.
 
-  auto* bar = MakeEmptyBodyFunction("bar");
-  bar->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* bar = MakeEmptyBodyFunction(
+      "bar",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
   mod()->AddFunction(bar);
 
   {
@@ -1256,9 +1315,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(ub_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "ub_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1287,9 +1348,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(ub_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "ub_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1310,9 +1373,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(ub_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "ub_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1337,9 +1402,11 @@
       "ub_func", "foo_ub", {{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
   mod()->AddFunction(ub_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "ub_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1386,11 +1453,11 @@
   AddFuncCall(body, "ub_baz_func");
 
   body->append(create<ast::ReturnStatement>());
-  ast::Function* func =
-      create<ast::Function>("ep_func", ast::VariableList(), void_type(), body);
-
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  ast::Function* func = create<ast::Function>(
+      Source{}, "ep_func", ast::VariableList(), void_type(), body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1423,9 +1490,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(ub_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "ub_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "ub_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1450,9 +1519,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1477,9 +1548,11 @@
       "sb_func", "foo_sb", {{0, i32_type()}, {1, u32_type()}, {2, f32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1526,11 +1599,11 @@
   AddFuncCall(body, "sb_baz_func");
 
   body->append(create<ast::ReturnStatement>());
-  ast::Function* func =
-      create<ast::Function>("ep_func", ast::VariableList(), void_type(), body);
-
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  ast::Function* func = create<ast::Function>(
+      Source{}, "ep_func", ast::VariableList(), void_type(), body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1563,9 +1636,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1590,9 +1665,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1617,9 +1694,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1640,9 +1719,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1691,11 +1772,11 @@
   AddFuncCall(body, "sb_baz_func");
 
   body->append(create<ast::ReturnStatement>());
-  ast::Function* func =
-      create<ast::Function>("ep_func", ast::VariableList(), void_type(), body);
-
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  ast::Function* func = create<ast::Function>(
+      Source{}, "ep_func", ast::VariableList(), void_type(), body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1729,9 +1810,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1758,9 +1841,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1786,9 +1871,11 @@
                                                           {{0, i32_type()}});
   mod()->AddFunction(sb_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "sb_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "sb_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1807,9 +1894,10 @@
   AddGlobalVariable("foo_coords", f32_type());
 
   auto* func = MakeSamplerReferenceBodyFunction(
-      "ep", "foo_texture", "foo_sampler", "foo_coords", f32_type());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "ep", "foo_texture", "foo_sampler", "foo_coords", f32_type(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1823,9 +1911,11 @@
 }
 
 TEST_F(InspectorGetSamplerResourceBindingsTest, NoSampler) {
-  auto* func = MakeEmptyBodyFunction("ep_func");
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = MakeEmptyBodyFunction(
+      "ep_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1847,9 +1937,11 @@
       "foo_func", "foo_texture", "foo_sampler", "foo_coords", f32_type());
   mod()->AddFunction(foo_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "foo_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "foo_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1870,9 +1962,10 @@
   AddGlobalVariable("foo_coords", f32_type());
 
   auto* func = MakeSamplerReferenceBodyFunction(
-      "ep", "foo_texture", "foo_sampler", "foo_coords", f32_type());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "ep", "foo_texture", "foo_sampler", "foo_coords", f32_type(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1890,10 +1983,10 @@
   AddGlobalVariable("foo_depth", f32_type());
 
   auto* func = MakeComparisonSamplerReferenceBodyFunction(
-      "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth",
-      f32_type());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", f32_type(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1913,10 +2006,10 @@
   AddGlobalVariable("foo_depth", f32_type());
 
   auto* func = MakeComparisonSamplerReferenceBodyFunction(
-      "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth",
-      f32_type());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", f32_type(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1930,9 +2023,11 @@
 }
 
 TEST_F(InspectorGetComparisonSamplerResourceBindingsTest, NoSampler) {
-  auto* func = MakeEmptyBodyFunction("ep_func");
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = MakeEmptyBodyFunction(
+      "ep_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1956,9 +2051,11 @@
       f32_type());
   mod()->AddFunction(foo_func);
 
-  auto* ep_func = MakeCallerBodyFunction("ep_func", "foo_func");
-  ep_func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_func = MakeCallerBodyFunction(
+      "ep_func", "foo_func",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(ep_func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -1980,10 +2077,10 @@
   AddGlobalVariable("foo_depth", f32_type());
 
   auto* func = MakeComparisonSamplerReferenceBodyFunction(
-      "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth",
-      f32_type());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_depth", f32_type(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -2000,9 +2097,10 @@
   AddGlobalVariable("foo_coords", f32_type());
 
   auto* func = MakeSamplerReferenceBodyFunction(
-      "ep", "foo_texture", "foo_sampler", "foo_coords", f32_type());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      "ep", "foo_texture", "foo_sampler", "foo_coords", f32_type(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -2014,9 +2112,11 @@
 }
 
 TEST_F(InspectorGetSampledTextureResourceBindingsTest, Empty) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   auto result = inspector()->GetSampledTextureResourceBindings("foo");
@@ -2036,9 +2136,10 @@
 
   auto* func = MakeSamplerReferenceBodyFunction(
       "ep", "foo_texture", "foo_sampler", "foo_coords",
-      GetBaseType(GetParam().sampled_kind));
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      GetBaseType(GetParam().sampled_kind),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -2119,9 +2220,10 @@
 
   auto* func = MakeSamplerReferenceBodyFunction(
       "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
-      GetBaseType(GetParam().sampled_kind));
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      GetBaseType(GetParam().sampled_kind),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -2189,9 +2291,10 @@
 
   auto* func = MakeSamplerReferenceBodyFunction(
       "ep", "foo_texture", "foo_sampler", "foo_coords",
-      GetBaseType(GetParam().sampled_kind));
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      GetBaseType(GetParam().sampled_kind),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
@@ -2236,9 +2339,11 @@
             inspector::ResourceBinding::SampledKind::kUInt}));
 
 TEST_F(InspectorGetMultisampledArrayTextureResourceBindingsTest, Empty) {
-  auto* foo = MakeEmptyBodyFunction("foo");
-  foo->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* foo = MakeEmptyBodyFunction(
+      "foo",
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(foo);
 
   auto result = inspector()->GetSampledTextureResourceBindings("foo");
@@ -2260,9 +2365,10 @@
 
   auto* func = MakeSamplerReferenceBodyFunction(
       "ep", "foo_texture", "foo_sampler", "foo_coords", "foo_array_index",
-      GetBaseType(GetParam().sampled_kind));
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+      GetBaseType(GetParam().sampled_kind),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   ASSERT_TRUE(td()->Determine()) << td()->error();
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 26e6580..84de22d 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -694,14 +694,13 @@
   if (failed()) {
     return false;
   }
-
-  auto* ast_fn = create<ast::Function>(name, std::move(ast_params), ret_ty,
-                                       create<ast::BlockStatement>());
-
+  ast::FunctionDecorationList decos;
   if (ep_info_ != nullptr) {
-    ast_fn->add_decoration(
-        create<ast::StageDecoration>(ep_info_->stage, Source{}));
+    decos.emplace_back(create<ast::StageDecoration>(ep_info_->stage, Source{}));
   }
+  auto* ast_fn =
+      create<ast::Function>(Source{}, name, std::move(ast_params), ret_ty,
+                            create<ast::BlockStatement>(), std::move(decos));
 
   ast_module_.AddFunction(ast_fn);
 
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index ec4a748..ad88c80 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -186,6 +186,21 @@
 
 }  // namespace
 
+ParserImpl::FunctionHeader::FunctionHeader() = default;
+
+ParserImpl::FunctionHeader::FunctionHeader(const FunctionHeader&) = default;
+
+ParserImpl::FunctionHeader::FunctionHeader(Source src,
+                                           std::string n,
+                                           ast::VariableList p,
+                                           ast::type::Type* ret_ty)
+    : source(src), name(n), params(p), return_type(ret_ty) {}
+
+ParserImpl::FunctionHeader::~FunctionHeader() = default;
+
+ParserImpl::FunctionHeader& ParserImpl::FunctionHeader::operator=(
+    const FunctionHeader& rhs) = default;
+
 ParserImpl::ParserImpl(Source::File const* file)
     : lexer_(std::make_unique<Lexer>(file)) {}
 
@@ -1238,8 +1253,8 @@
 // function_decl
 //   : function_header body_stmt
 Maybe<ast::Function*> ParserImpl::function_decl(ast::DecorationList& decos) {
-  auto f = function_header();
-  if (f.errored) {
+  auto header = function_header();
+  if (header.errored) {
     if (sync_to(Token::Type::kBraceLeft, /* consume: */ false)) {
       // There were errors in the function header, but the parser has managed to
       // resynchronize with the opening brace. As there's no outer
@@ -1251,7 +1266,7 @@
     }
     return Failure::kErrored;
   }
-  if (!f.matched)
+  if (!header.matched)
     return Failure::kNoMatch;
 
   bool errored = false;
@@ -1260,8 +1275,6 @@
   if (func_decos.errored)
     errored = true;
 
-  f->set_decorations(std::move(func_decos.value));
-
   auto body = expect_body_stmt();
   if (body.errored)
     errored = true;
@@ -1269,8 +1282,9 @@
   if (errored)
     return Failure::kErrored;
 
-  f->set_body(body.value);
-  return f.value;
+  return create<ast::Function>(header->source, header->name, header->params,
+                               header->return_type, body.value,
+                               func_decos.value);
 }
 
 // function_type_decl
@@ -1285,7 +1299,7 @@
 
 // function_header
 //   : FN IDENT PAREN_LEFT param_list PAREN_RIGHT ARROW function_type_decl
-Maybe<ast::Function*> ParserImpl::function_header() {
+Maybe<ParserImpl::FunctionHeader> ParserImpl::function_header() {
   Source source;
   if (!match(Token::Type::kFn, &source))
     return Failure::kNoMatch;
@@ -1320,8 +1334,8 @@
   if (errored)
     return Failure::kErrored;
 
-  return create<ast::Function>(source, name.value, std::move(params.value),
-                               type.value, create<ast::BlockStatement>());
+  return FunctionHeader{source, name.value, std::move(params.value),
+                        type.value};
 }
 
 // param_list
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 5ee8fe2..3feea22 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -229,6 +229,39 @@
     Source source;
   };
 
+  /// FunctionHeader contains the parsed information for a function header.
+  struct FunctionHeader {
+    /// Constructor
+    FunctionHeader();
+    /// Copy constructor
+    /// @param other the FunctionHeader to copy
+    FunctionHeader(const FunctionHeader& other);
+    /// Constructor
+    /// @param src parsed header source
+    /// @param n function name
+    /// @param p function parameters
+    /// @param ret_ty function return type
+    FunctionHeader(Source src,
+                   std::string n,
+                   ast::VariableList p,
+                   ast::type::Type* ret_ty);
+    /// Destructor
+    ~FunctionHeader();
+    /// Assignment operator
+    /// @param other the FunctionHeader to copy
+    /// @returns this FunctionHeader
+    FunctionHeader& operator=(const FunctionHeader& other);
+
+    /// Parsed header source
+    Source source;
+    /// Function name
+    std::string name;
+    /// Function parameters
+    ast::VariableList params;
+    /// Function return type
+    ast::type::Type* return_type;
+  };
+
   /// Creates a new parser using the given file
   /// @param file the input source file to parse
   explicit ParserImpl(Source::File const* file);
@@ -398,8 +431,8 @@
   /// @returns the parsed type or nullptr otherwise
   Maybe<ast::type::Type*> function_type_decl();
   /// Parses a `function_header` grammar element
-  /// @returns the parsed function nullptr otherwise
-  Maybe<ast::Function*> function_header();
+  /// @returns the parsed function header
+  Maybe<FunctionHeader> function_header();
   /// Parses a `param_list` grammar element, erroring on parse failure.
   /// @returns the parsed variables
   Expect<ast::VariableList> expect_param_list();
diff --git a/src/reader/wgsl/parser_impl_function_header_test.cc b/src/reader/wgsl/parser_impl_function_header_test.cc
index e6a9e15..9b53b21 100644
--- a/src/reader/wgsl/parser_impl_function_header_test.cc
+++ b/src/reader/wgsl/parser_impl_function_header_test.cc
@@ -30,13 +30,12 @@
   ASSERT_FALSE(p->has_error()) << p->error();
   EXPECT_TRUE(f.matched);
   EXPECT_FALSE(f.errored);
-  ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->name(), "main");
-  ASSERT_EQ(f->params().size(), 2u);
-  EXPECT_EQ(f->params()[0]->name(), "a");
-  EXPECT_EQ(f->params()[1]->name(), "b");
-  EXPECT_TRUE(f->return_type()->Is<ast::type::Void>());
+  EXPECT_EQ(f->name, "main");
+  ASSERT_EQ(f->params.size(), 2u);
+  EXPECT_EQ(f->params[0]->name(), "a");
+  EXPECT_EQ(f->params[1]->name(), "b");
+  EXPECT_TRUE(f->return_type->Is<ast::type::Void>());
 }
 
 TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
@@ -45,7 +44,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
 }
 
@@ -55,7 +53,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:4: expected identifier for function declaration");
 }
 
@@ -65,7 +62,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:8: expected '(' for function declaration");
 }
 
@@ -75,7 +71,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:16: expected identifier for parameter");
 }
 
@@ -85,7 +80,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:10: expected ')' for function declaration");
 }
 
@@ -95,7 +89,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:11: expected '->' for function declaration");
 }
 
@@ -105,7 +98,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:14: unknown constructed type 'invalid'");
 }
 
@@ -115,7 +107,6 @@
   EXPECT_FALSE(f.matched);
   EXPECT_TRUE(f.errored);
   EXPECT_TRUE(p->has_error());
-  EXPECT_EQ(f.value, nullptr);
   EXPECT_EQ(p->error(), "1:13: unable to determine function return type");
 }
 
diff --git a/src/transform/bound_array_accessors_test.cc b/src/transform/bound_array_accessors_test.cc
index c1fc4e6..2bb7f5b 100644
--- a/src/transform/bound_array_accessors_test.cc
+++ b/src/transform/bound_array_accessors_test.cc
@@ -92,8 +92,9 @@
 
 struct ModuleBuilder : public ast::BuilderWithModule {
   ModuleBuilder() : body_(create<ast::BlockStatement>()) {
-    mod->AddFunction(
-        create<ast::Function>("func", ast::VariableList{}, ty.void_, body_));
+    mod->AddFunction(create<ast::Function>(Source{}, "func",
+                                           ast::VariableList{}, ty.void_, body_,
+                                           ast::FunctionDecorationList{}));
   }
 
   ast::Module Module() {
diff --git a/src/transform/emit_vertex_point_size_test.cc b/src/transform/emit_vertex_point_size_test.cc
index 4db8a57..55eebf2 100644
--- a/src/transform/emit_vertex_point_size_test.cc
+++ b/src/transform/emit_vertex_point_size_test.cc
@@ -59,18 +59,22 @@
               tint::ast::StorageClass::kFunction, ty.f32)));
 
       mod->AddFunction(
-          create<ast::Function>("non_entry_a", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{})));
+          create<ast::Function>(Source{}, "non_entry_a", ast::VariableList{},
+                                ty.void_, create<ast::BlockStatement>(Source{}),
+                                ast::FunctionDecorationList{}));
 
-      auto* entry =
-          create<ast::Function>("entry", ast::VariableList{}, ty.void_, block);
-      entry->set_decorations({create<ast::StageDecoration>(
-          ast::PipelineStage::kVertex, Source{})});
+      auto* entry = create<ast::Function>(
+          Source{}, "entry", ast::VariableList{}, ty.void_, block,
+          ast::FunctionDecorationList{
+              create<ast::StageDecoration>(ast::PipelineStage::kVertex,
+                                           Source{}),
+          });
       mod->AddFunction(entry);
 
       mod->AddFunction(
-          create<ast::Function>("non_entry_b", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{})));
+          create<ast::Function>(Source{}, "non_entry_b", ast::VariableList{},
+                                ty.void_, create<ast::BlockStatement>(Source{}),
+                                ast::FunctionDecorationList{}));
     }
   };
 
@@ -120,19 +124,22 @@
   struct Builder : ModuleBuilder {
     void Build() override {
       mod->AddFunction(
-          create<ast::Function>("non_entry_a", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{})));
-
-      auto* entry =
-          create<ast::Function>("entry", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{}));
-      entry->set_decorations({create<ast::StageDecoration>(
-          ast::PipelineStage::kVertex, Source{})});
-      mod->AddFunction(entry);
+          create<ast::Function>(Source{}, "non_entry_a", ast::VariableList{},
+                                ty.void_, create<ast::BlockStatement>(Source{}),
+                                ast::FunctionDecorationList{}));
 
       mod->AddFunction(
-          create<ast::Function>("non_entry_b", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{})));
+          create<ast::Function>(Source{}, "entry", ast::VariableList{},
+                                ty.void_, create<ast::BlockStatement>(Source{}),
+                                ast::FunctionDecorationList{
+                                    create<ast::StageDecoration>(
+                                        ast::PipelineStage::kVertex, Source{}),
+                                }));
+
+      mod->AddFunction(
+          create<ast::Function>(Source{}, "non_entry_b", ast::VariableList{},
+                                ty.void_, create<ast::BlockStatement>(Source{}),
+                                ast::FunctionDecorationList{}));
     }
   };
 
@@ -174,18 +181,22 @@
 TEST_F(EmitVertexPointSizeTest, NonVertexStage) {
   struct Builder : ModuleBuilder {
     void Build() override {
-      auto* fragment_entry =
-          create<ast::Function>("fragment_entry", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{}));
-      fragment_entry->set_decorations({create<ast::StageDecoration>(
-          ast::PipelineStage::kFragment, Source{})});
+      auto* fragment_entry = create<ast::Function>(
+          Source{}, "fragment_entry", ast::VariableList{}, ty.void_,
+          create<ast::BlockStatement>(Source{}),
+          ast::FunctionDecorationList{
+              create<ast::StageDecoration>(ast::PipelineStage::kFragment,
+                                           Source{}),
+          });
       mod->AddFunction(fragment_entry);
 
       auto* compute_entry =
-          create<ast::Function>("compute_entry", ast::VariableList{}, ty.void_,
-                                create<ast::BlockStatement>(Source{}));
-      compute_entry->set_decorations({create<ast::StageDecoration>(
-          ast::PipelineStage::kCompute, Source{})});
+          create<ast::Function>(Source{}, "compute_entry", ast::VariableList{},
+                                ty.void_, create<ast::BlockStatement>(Source{}),
+                                ast::FunctionDecorationList{
+                                    create<ast::StageDecoration>(
+                                        ast::PipelineStage::kCompute, Source{}),
+                                });
       mod->AddFunction(compute_entry);
     }
   };
diff --git a/src/transform/vertex_pulling_test.cc b/src/transform/vertex_pulling_test.cc
index 942c2c5..a2eb2c9 100644
--- a/src/transform/vertex_pulling_test.cc
+++ b/src/transform/vertex_pulling_test.cc
@@ -46,11 +46,11 @@
 
   // Create basic module with an entry point and vertex function
   void InitBasicModule() {
-    auto* func = create<ast::Function>("main", ast::VariableList{},
-                                       mod_->create<ast::type::Void>(),
-                                       create<ast::BlockStatement>());
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+    auto* func = create<ast::Function>(
+        Source{}, "main", ast::VariableList{}, mod_->create<ast::type::Void>(),
+        create<ast::BlockStatement>(),
+        ast::FunctionDecorationList{create<ast::StageDecoration>(
+            ast::PipelineStage::kVertex, Source{})});
     mod()->AddFunction(func);
   }
 
@@ -128,11 +128,12 @@
 }
 
 TEST_F(VertexPullingTest, Error_EntryPointWrongStage) {
-  auto* func = create<ast::Function>("main", ast::VariableList{},
-                                     mod()->create<ast::type::Void>(),
-                                     create<ast::BlockStatement>());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", ast::VariableList{}, mod()->create<ast::type::Void>(),
+      create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
   mod()->AddFunction(func);
 
   InitTransform({});
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index fc1df28..8af4a49 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -340,8 +340,9 @@
   ast::type::F32 f32;
 
   ast::VariableList params;
-  auto* func = create<ast::Function>("my_func", params, &f32,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32,
+                                     create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod->AddFunction(func);
 
   // Register the function
@@ -370,12 +371,15 @@
   auto* main_body = create<ast::BlockStatement>();
   main_body->append(create<ast::CallStatement>(call_expr));
   main_body->append(create<ast::ReturnStatement>());
-  auto* func_main = create<ast::Function>("main", params0, &f32, main_body);
+  auto* func_main =
+      create<ast::Function>(Source{}, "main", params0, &f32, main_body,
+                            ast::FunctionDecorationList{});
   mod->AddFunction(func_main);
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("func", params0, &f32, body);
+  auto* func = create<ast::Function>(Source{}, "func", params0, &f32, body,
+                                     ast::FunctionDecorationList{});
   mod->AddFunction(func);
 
   EXPECT_FALSE(td()->Determine()) << td()->error();
@@ -583,8 +587,9 @@
   ast::type::F32 f32;
 
   ast::VariableList params;
-  auto* func = create<ast::Function>("my_func", params, &f32,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32,
+                                     create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod->AddFunction(func);
 
   // Register the function
@@ -602,8 +607,9 @@
   ast::type::F32 f32;
 
   ast::VariableList params;
-  auto* func = create<ast::Function>("my_func", params, &f32,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32,
+                                     create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod->AddFunction(func);
 
   // Register the function
@@ -732,7 +738,8 @@
   body->append(create<ast::AssignmentStatement>(
       my_var, create<ast::IdentifierExpression>("my_var")));
 
-  ast::Function f("my_func", {}, &f32, body);
+  ast::Function f(Source{}, "my_func", {}, &f32, body,
+                  ast::FunctionDecorationList{});
 
   EXPECT_TRUE(td()->DetermineFunction(&f));
 
@@ -752,7 +759,8 @@
   body->append(create<ast::AssignmentStatement>(
       my_var, create<ast::IdentifierExpression>("my_var")));
 
-  ast::Function f("my_func", {}, &f32, body);
+  ast::Function f(Source{}, "my_func", {}, &f32, body,
+                  ast::FunctionDecorationList{});
 
   EXPECT_TRUE(td()->DetermineFunction(&f));
 
@@ -777,7 +785,8 @@
   body->append(create<ast::AssignmentStatement>(
       my_var, create<ast::IdentifierExpression>("my_var")));
 
-  ast::Function f("my_func", {}, &f32, body);
+  ast::Function f(Source{}, "my_func", {}, &f32, body,
+                  ast::FunctionDecorationList{});
 
   EXPECT_TRUE(td()->DetermineFunction(&f));
 
@@ -793,8 +802,9 @@
   ast::type::F32 f32;
 
   ast::VariableList params;
-  auto* func = create<ast::Function>("my_func", params, &f32,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32,
+                                     create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod->AddFunction(func);
 
   // Register the function
@@ -845,7 +855,8 @@
   body->append(create<ast::AssignmentStatement>(
       create<ast::IdentifierExpression>("priv_var"),
       create<ast::IdentifierExpression>("priv_var")));
-  auto* func = create<ast::Function>("my_func", params, &f32, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32, body,
+                                     ast::FunctionDecorationList{});
 
   mod->AddFunction(func);
 
@@ -895,7 +906,8 @@
       create<ast::IdentifierExpression>("priv_var"),
       create<ast::IdentifierExpression>("priv_var")));
   ast::VariableList params;
-  auto* func = create<ast::Function>("my_func", params, &f32, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32, body,
+                                     ast::FunctionDecorationList{});
 
   mod->AddFunction(func);
 
@@ -904,7 +916,8 @@
       create<ast::IdentifierExpression>("out_var"),
       create<ast::CallExpression>(create<ast::IdentifierExpression>("my_func"),
                                   ast::ExpressionList{})));
-  auto* func2 = create<ast::Function>("func", params, &f32, body);
+  auto* func2 = create<ast::Function>(Source{}, "func", params, &f32, body,
+                                      ast::FunctionDecorationList{});
 
   mod->AddFunction(func2);
 
@@ -934,7 +947,8 @@
           create<ast::FloatLiteral>(&f32, 1.f))));
 
   ast::VariableList params;
-  auto* func = create<ast::Function>("my_func", params, &f32, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32, body,
+                                     ast::FunctionDecorationList{});
 
   mod->AddFunction(func);
 
@@ -2154,7 +2168,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(stmt);
-  auto* func = create<ast::Function>("func", ast::VariableList{}, &i32, body);
+  auto* func = create<ast::Function>(Source{}, "func", ast::VariableList{},
+                                     &i32, body, ast::FunctionDecorationList{});
 
   mod->AddFunction(func);
 
@@ -2171,7 +2186,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(stmt);
-  auto* func = create<ast::Function>("func", ast::VariableList{}, &i32, body);
+  auto* func = create<ast::Function>(Source{}, "func", ast::VariableList{},
+                                     &i32, body, ast::FunctionDecorationList{});
 
   mod->AddFunction(func);
 
@@ -2187,7 +2203,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(stmt);
-  auto* func = create<ast::Function>("func", ast::VariableList{}, &i32, body);
+  auto* func = create<ast::Function>(Source{}, "func", ast::VariableList{},
+                                     &i32, body, ast::FunctionDecorationList{});
 
   mod->AddFunction(func);
 
@@ -4338,21 +4355,24 @@
 
   ast::VariableList params;
   auto* body = create<ast::BlockStatement>();
-  auto* func_b = create<ast::Function>("b", params, &f32, body);
+  auto* func_b = create<ast::Function>(Source{}, "b", params, &f32, body,
+                                       ast::FunctionDecorationList{});
 
   body = create<ast::BlockStatement>();
   body->append(create<ast::AssignmentStatement>(
       create<ast::IdentifierExpression>("second"),
       create<ast::CallExpression>(create<ast::IdentifierExpression>("b"),
                                   ast::ExpressionList{})));
-  auto* func_c = create<ast::Function>("c", params, &f32, body);
+  auto* func_c = create<ast::Function>(Source{}, "c", params, &f32, body,
+                                       ast::FunctionDecorationList{});
 
   body = create<ast::BlockStatement>();
   body->append(create<ast::AssignmentStatement>(
       create<ast::IdentifierExpression>("first"),
       create<ast::CallExpression>(create<ast::IdentifierExpression>("c"),
                                   ast::ExpressionList{})));
-  auto* func_a = create<ast::Function>("a", params, &f32, body);
+  auto* func_a = create<ast::Function>(Source{}, "a", params, &f32, body,
+                                       ast::FunctionDecorationList{});
 
   body = create<ast::BlockStatement>();
   body->append(create<ast::AssignmentStatement>(
@@ -4363,18 +4383,22 @@
       create<ast::IdentifierExpression>("call_b"),
       create<ast::CallExpression>(create<ast::IdentifierExpression>("b"),
                                   ast::ExpressionList{})));
-  auto* ep_1 = create<ast::Function>("ep_1", params, &f32, body);
-  ep_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   body = create<ast::BlockStatement>();
   body->append(create<ast::AssignmentStatement>(
       create<ast::IdentifierExpression>("call_c"),
       create<ast::CallExpression>(create<ast::IdentifierExpression>("c"),
                                   ast::ExpressionList{})));
-  auto* ep_2 = create<ast::Function>("ep_2", params, &f32, body);
-  ep_2->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* ep_2 = create<ast::Function>(
+      Source{}, "ep_2", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod->AddFunction(func_b);
   mod->AddFunction(func_c);
diff --git a/src/validator/validator_function_test.cc b/src/validator/validator_function_test.cc
index 4bb5d7c..c767789 100644
--- a/src/validator/validator_function_test.cc
+++ b/src/validator/validator_function_test.cc
@@ -47,10 +47,11 @@
   ast::type::Void void_type;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
-  auto* func = create<ast::Function>(Source{Source::Location{12, 34}}, "func",
-                                     params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{Source::Location{12, 34}}, "func", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -63,11 +64,12 @@
   // fn func -> void {}
   ast::type::Void void_type;
   ast::VariableList params;
-  auto* func =
-      create<ast::Function>(Source{Source::Location{12, 34}}, "func", params,
-                            &void_type, create<ast::BlockStatement>());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{Source::Location{12, 34}}, "func", params, &void_type,
+      create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -86,8 +88,9 @@
   ast::type::Void void_type;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
-  auto* func = create<ast::Function>(Source{Source::Location{12, 34}}, "func",
-                                     params, &i32, body);
+  auto* func =
+      create<ast::Function>(Source{Source::Location{12, 34}}, "func", params,
+                            &i32, body, ast::FunctionDecorationList{});
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -101,9 +104,9 @@
   ast::type::Void void_type;
   ast::type::I32 i32;
   ast::VariableList params;
-  auto* func =
-      create<ast::Function>(Source{Source::Location{12, 34}}, "func", params,
-                            &i32, create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(
+      Source{Source::Location{12, 34}}, "func", params, &i32,
+      create<ast::BlockStatement>(), ast::FunctionDecorationList{});
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -120,9 +123,11 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("func", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "func", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->DetermineFunctions(mod()->functions())) << td()->error();
@@ -140,7 +145,8 @@
 
   body->append(create<ast::ReturnStatement>(Source{Source::Location{12, 34}},
                                             return_expr));
-  auto* func = create<ast::Function>("func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "func", params, &void_type, body,
+                                     ast::FunctionDecorationList{});
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -162,7 +168,8 @@
 
   body->append(create<ast::ReturnStatement>(Source{Source::Location{12, 34}},
                                             return_expr));
-  auto* func = create<ast::Function>("func", params, &f32, body);
+  auto* func = create<ast::Function>(Source{}, "func", params, &f32, body,
+                                     ast::FunctionDecorationList{});
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -185,7 +192,8 @@
       create<ast::SintLiteral>(&i32, 2));
 
   body->append(create<ast::ReturnStatement>(return_expr));
-  auto* func = create<ast::Function>("func", params, &i32, body);
+  auto* func = create<ast::Function>(Source{}, "func", params, &i32, body,
+                                     ast::FunctionDecorationList{});
 
   ast::VariableList params_copy;
   auto* body_copy = create<ast::BlockStatement>();
@@ -194,7 +202,8 @@
 
   body_copy->append(create<ast::ReturnStatement>(return_expr_copy));
   auto* func_copy = create<ast::Function>(Source{Source::Location{12, 34}},
-                                          "func", params_copy, &i32, body_copy);
+                                          "func", params_copy, &i32, body_copy,
+                                          ast::FunctionDecorationList{});
 
   mod()->AddFunction(func);
   mod()->AddFunction(func_copy);
@@ -216,7 +225,8 @@
   auto* body0 = create<ast::BlockStatement>();
   body0->append(create<ast::CallStatement>(call_expr));
   body0->append(create<ast::ReturnStatement>());
-  auto* func0 = create<ast::Function>("func", params0, &f32, body0);
+  auto* func0 = create<ast::Function>(Source{}, "func", params0, &f32, body0,
+                                      ast::FunctionDecorationList{});
   mod()->AddFunction(func0);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -240,7 +250,8 @@
       create<ast::SintLiteral>(&i32, 2));
 
   body0->append(create<ast::ReturnStatement>(return_expr));
-  auto* func0 = create<ast::Function>("func", params0, &i32, body0);
+  auto* func0 = create<ast::Function>(Source{}, "func", params0, &i32, body0,
+                                      ast::FunctionDecorationList{});
   mod()->AddFunction(func0);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -258,10 +269,11 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>(return_expr));
-  auto* func = create<ast::Function>(Source{Source::Location{12, 34}},
-                                     "vtx_main", params, &i32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{Source::Location{12, 34}}, "vtx_main", params, &i32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod()->AddFunction(func);
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -279,10 +291,11 @@
   params.push_back(create<ast::Variable>("a", ast::StorageClass::kNone, &i32));
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>(Source{Source::Location{12, 34}},
-                                     "vtx_func", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{Source::Location{12, 34}}, "vtx_func", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod()->AddFunction(func);
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -300,12 +313,13 @@
   ast::VariableList params;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>(Source{Source::Location{12, 34}}, "main",
-                                     params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{Source::Location{12, 34}}, "main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
+
   mod()->AddFunction(func);
   EXPECT_TRUE(td()->Determine()) << td()->error();
   EXPECT_FALSE(v()->Validate(mod()));
@@ -321,9 +335,11 @@
   ast::VariableList params;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("vtx_func", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "vtx_func", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -336,7 +352,8 @@
   ast::VariableList params;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("vtx_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "vtx_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
diff --git a/src/validator/validator_test.cc b/src/validator/validator_test.cc
index 1978a18..6c5871b 100644
--- a/src/validator/validator_test.cc
+++ b/src/validator/validator_test.cc
@@ -290,7 +290,8 @@
   body->append(create<ast::AssignmentStatement>(
       Source{Source::Location{12, 34}}, lhs, rhs));
 
-  auto* func = create<ast::Function>("my_func", params, &f32, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &f32, body,
+                                     ast::FunctionDecorationList{});
   mod()->AddFunction(func);
 
   EXPECT_FALSE(v()->Validate(mod()));
@@ -322,9 +323,11 @@
   body->append(create<ast::AssignmentStatement>(
       Source{Source::Location{12, 34}}, lhs, rhs));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "my_func", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
@@ -492,7 +495,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(
       Source{Source::Location{12, 34}}, var));
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
 
   mod()->AddFunction(func);
 
@@ -524,7 +528,8 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::VariableDeclStatement>(
       Source{Source::Location{12, 34}}, var_a_float));
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
 
   mod()->AddFunction(func);
 
@@ -617,16 +622,19 @@
   body0->append(create<ast::VariableDeclStatement>(
       Source{Source::Location{12, 34}}, var0));
   body0->append(create<ast::ReturnStatement>());
-  auto* func0 = create<ast::Function>("func0", params0, &void_type, body0);
+  auto* func0 = create<ast::Function>(Source{}, "func0", params0, &void_type,
+                                      body0, ast::FunctionDecorationList{});
 
   ast::VariableList params1;
   auto* body1 = create<ast::BlockStatement>();
   body1->append(create<ast::VariableDeclStatement>(
       Source{Source::Location{13, 34}}, var1));
   body1->append(create<ast::ReturnStatement>());
-  auto* func1 = create<ast::Function>("func1", params1, &void_type, body1);
-  func1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func1 = create<ast::Function>(
+      Source{}, "func1", params1, &void_type, body1,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod()->AddFunction(func0);
   mod()->AddFunction(func1);
diff --git a/src/validator/validator_type_test.cc b/src/validator/validator_type_test.cc
index f9d6c71..48bbc33 100644
--- a/src/validator/validator_type_test.cc
+++ b/src/validator/validator_type_test.cc
@@ -199,9 +199,11 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(
       Source{Source::Location{12, 34}}, var));
-  auto* func = create<ast::Function>("func", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "func", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
   mod()->AddFunction(func);
 
   EXPECT_TRUE(td()->Determine()) << td()->error();
diff --git a/src/writer/hlsl/generator_impl_binary_test.cc b/src/writer/hlsl/generator_impl_binary_test.cc
index 52e5fff..37bc11a 100644
--- a/src/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/writer/hlsl/generator_impl_binary_test.cc
@@ -534,8 +534,9 @@
 
   ast::type::Void void_type;
 
-  auto* func = create<ast::Function>("foo", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "foo", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   ast::ExpressionList params;
diff --git a/src/writer/hlsl/generator_impl_call_test.cc b/src/writer/hlsl/generator_impl_call_test.cc
index 780b253..e185dcc 100644
--- a/src/writer/hlsl/generator_impl_call_test.cc
+++ b/src/writer/hlsl/generator_impl_call_test.cc
@@ -35,8 +35,9 @@
   auto* id = create<ast::IdentifierExpression>("my_func");
   ast::CallExpression call(id, {});
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &call)) << gen.error();
@@ -52,8 +53,9 @@
   params.push_back(create<ast::IdentifierExpression>("param2"));
   ast::CallExpression call(id, params);
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &call)) << gen.error();
@@ -69,8 +71,9 @@
   params.push_back(create<ast::IdentifierExpression>("param2"));
   ast::CallStatement call(create<ast::CallExpression>(id, params));
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
   gen.increment_indent();
   ASSERT_TRUE(gen.EmitStatement(out, &call)) << gen.error();
diff --git a/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc b/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
index 24448a2..38e5cfd 100644
--- a/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
+++ b/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
@@ -75,9 +75,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("vtx_main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "vtx_main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -130,9 +132,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("vtx_main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "vtx_main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -185,9 +189,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -239,9 +245,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -294,9 +302,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -344,9 +354,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -398,9 +410,11 @@
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("x"))));
 
-  auto* func = create<ast::Function>("main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc
index b3bb0e7..c8ac19f 100644
--- a/src/writer/hlsl/generator_impl_function_test.cc
+++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -59,7 +59,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
   auto* func =
-      create<ast::Function>("my_func", ast::VariableList{}, &void_type, body);
+      create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                            &void_type, body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -77,8 +78,9 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("GeometryShader", ast::VariableList{},
-                                     &void_type, body);
+  auto* func =
+      create<ast::Function>(Source{}, "GeometryShader", ast::VariableList{},
+                            &void_type, body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -103,7 +105,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -141,9 +144,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("foo")));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -197,9 +202,11 @@
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("x"))));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -248,9 +255,11 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -306,9 +315,11 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -368,9 +379,11 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -426,9 +439,11 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -487,9 +502,11 @@
   auto* body = create<ast::BlockStatement>();
   body->append(assign);
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -544,7 +561,8 @@
       create<ast::IdentifierExpression>("param")));
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("foo")));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -558,9 +576,11 @@
       create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
                                   expr)));
   body->append(create<ast::ReturnStatement>());
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -615,7 +635,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("param")));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -629,9 +650,11 @@
       create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
                                   expr)));
   body->append(create<ast::ReturnStatement>());
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -689,7 +712,8 @@
           create<ast::IdentifierExpression>("x"))));
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("param")));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -703,9 +727,11 @@
       create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
                                   expr)));
   body->append(create<ast::ReturnStatement>());
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -760,7 +786,8 @@
       create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("x"))));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -775,9 +802,11 @@
   body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -826,7 +855,8 @@
       create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("x"))));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -841,9 +871,11 @@
   body = create<ast::BlockStatement>();
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -898,9 +930,11 @@
       list, ast::ElseStatementList{}));
 
   body->append(create<ast::ReturnStatement>());
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -926,10 +960,12 @@
        Emit_FunctionDecoration_EntryPoint_WithNameCollision) {
   ast::type::Void void_type;
 
-  auto* func = create<ast::Function>("GeometryShader", ast::VariableList{},
-                                     &void_type, create<ast::BlockStatement>());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "GeometryShader", ast::VariableList{}, &void_type,
+      create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -947,9 +983,11 @@
   ast::VariableList params;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -970,10 +1008,12 @@
   ast::VariableList params;
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
-  func->add_decoration(create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+          create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -998,7 +1038,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -1067,9 +1108,12 @@
     auto* body = create<ast::BlockStatement>();
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
-    auto* func = create<ast::Function>("a", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "a", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod.AddFunction(func);
   }
@@ -1084,9 +1128,12 @@
     auto* body = create<ast::BlockStatement>();
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
-    auto* func = create<ast::Function>("b", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "b", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod.AddFunction(func);
   }
diff --git a/src/writer/hlsl/generator_impl_test.cc b/src/writer/hlsl/generator_impl_test.cc
index 4f0a14c..dfdaf95 100644
--- a/src/writer/hlsl/generator_impl_test.cc
+++ b/src/writer/hlsl/generator_impl_test.cc
@@ -29,8 +29,9 @@
 
 TEST_F(HlslGeneratorImplTest, Generate) {
   ast::type::Void void_type;
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   ASSERT_TRUE(gen.Generate(out)) << gen.error();
diff --git a/src/writer/msl/generator_impl_call_test.cc b/src/writer/msl/generator_impl_call_test.cc
index 0041ed7..c27e556 100644
--- a/src/writer/msl/generator_impl_call_test.cc
+++ b/src/writer/msl/generator_impl_call_test.cc
@@ -37,8 +37,9 @@
   auto* id = create<ast::IdentifierExpression>("my_func");
   ast::CallExpression call(id, {});
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   ASSERT_TRUE(gen.EmitExpression(&call)) << gen.error();
@@ -54,8 +55,9 @@
   params.push_back(create<ast::IdentifierExpression>("param2"));
   ast::CallExpression call(id, params);
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   ASSERT_TRUE(gen.EmitExpression(&call)) << gen.error();
@@ -71,8 +73,9 @@
   params.push_back(create<ast::IdentifierExpression>("param2"));
   ast::CallStatement call(create<ast::CallExpression>(id, params));
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
+  auto* func = create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                                     &void_type, create<ast::BlockStatement>(),
+                                     ast::FunctionDecorationList{});
   mod.AddFunction(func);
 
   gen.increment_indent();
diff --git a/src/writer/msl/generator_impl_function_entry_point_data_test.cc b/src/writer/msl/generator_impl_function_entry_point_data_test.cc
index 819085e..62f6286 100644
--- a/src/writer/msl/generator_impl_function_entry_point_data_test.cc
+++ b/src/writer/msl/generator_impl_function_entry_point_data_test.cc
@@ -74,9 +74,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("vtx_main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "vtx_main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -126,9 +128,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("vtx_main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "vtx_main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -177,9 +181,11 @@
   body->append(create<ast::AssignmentStatement>(
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -229,9 +235,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -282,9 +290,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -330,9 +340,11 @@
       create<ast::IdentifierExpression>("bar"),
       create<ast::IdentifierExpression>("bar")));
 
-  auto* func = create<ast::Function>("main", params, &f32, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &f32, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -382,9 +394,11 @@
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("x"))));
 
-  auto* func = create<ast::Function>("main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 088455a..453aaa8 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -62,7 +62,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
   auto* func =
-      create<ast::Function>("my_func", ast::VariableList{}, &void_type, body);
+      create<ast::Function>(Source{}, "my_func", ast::VariableList{},
+                            &void_type, body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -83,7 +84,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
   auto* func =
-      create<ast::Function>("main", ast::VariableList{}, &void_type, body);
+      create<ast::Function>(Source{}, "main", ast::VariableList{}, &void_type,
+                            body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -110,7 +112,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
   gen.increment_indent();
@@ -150,9 +153,10 @@
       create<ast::IdentifierExpression>("foo")));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{create<ast::StageDecoration>(
+          ast::PipelineStage::kFragment, Source{})});
 
   mod.AddFunction(func);
 
@@ -209,9 +213,11 @@
           create<ast::IdentifierExpression>("x"))));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -260,9 +266,11 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -323,9 +331,11 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -391,9 +401,11 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -454,7 +466,8 @@
       create<ast::IdentifierExpression>("param")));
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("foo")));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -468,9 +481,11 @@
       create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
                                   expr)));
   body->append(create<ast::ReturnStatement>());
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -528,7 +543,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("param")));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -543,9 +559,11 @@
                                   expr)));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -606,7 +624,8 @@
           create<ast::IdentifierExpression>("x"))));
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("param")));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -620,9 +639,11 @@
       create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
                                   expr)));
   body->append(create<ast::ReturnStatement>());
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -675,7 +696,8 @@
       create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("x"))));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -691,9 +713,11 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -755,7 +779,8 @@
       create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("b"))));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -771,9 +796,11 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -841,7 +868,8 @@
       create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
           create<ast::IdentifierExpression>("coord"),
           create<ast::IdentifierExpression>("b"))));
-  auto* sub_func = create<ast::Function>("sub_func", params, &f32, body);
+  auto* sub_func = create<ast::Function>(Source{}, "sub_func", params, &f32,
+                                         body, ast::FunctionDecorationList{});
 
   mod.AddFunction(sub_func);
 
@@ -857,9 +885,11 @@
   body->append(create<ast::VariableDeclStatement>(var));
   body->append(create<ast::ReturnStatement>());
 
-  auto* func = create<ast::Function>("frag_main", params, &void_type, body);
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "frag_main", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -921,9 +951,11 @@
 
   body->append(create<ast::ReturnStatement>());
 
-  auto* func_1 = create<ast::Function>("ep_1", params, &void_type, body);
-  func_1->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  auto* func_1 = create<ast::Function>(
+      Source{}, "ep_1", params, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   mod.AddFunction(func_1);
 
@@ -951,10 +983,12 @@
        Emit_FunctionDecoration_EntryPoint_WithNameCollision) {
   ast::type::Void void_type;
 
-  auto* func = create<ast::Function>("main", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "main", ast::VariableList{}, &void_type,
+      create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   mod.AddFunction(func);
 
@@ -978,7 +1012,8 @@
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
-  auto* func = create<ast::Function>("my_func", params, &void_type, body);
+  auto* func = create<ast::Function>(Source{}, "my_func", params, &void_type,
+                                     body, ast::FunctionDecorationList{});
 
   mod.AddFunction(func);
 
@@ -1052,9 +1087,12 @@
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
 
-    auto* func = create<ast::Function>("a", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "a", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod.AddFunction(func);
   }
@@ -1070,9 +1108,12 @@
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
 
-    auto* func = create<ast::Function>("b", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "b", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod.AddFunction(func);
   }
diff --git a/src/writer/msl/generator_impl_test.cc b/src/writer/msl/generator_impl_test.cc
index b366f44..c32e429 100644
--- a/src/writer/msl/generator_impl_test.cc
+++ b/src/writer/msl/generator_impl_test.cc
@@ -50,10 +50,12 @@
 TEST_F(MslGeneratorImplTest, Generate) {
   ast::type::Void void_type;
 
-  auto* func = create<ast::Function>("my_func", ast::VariableList{}, &void_type,
-                                     create<ast::BlockStatement>());
-  func->add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  auto* func = create<ast::Function>(
+      Source{}, "my_func", ast::VariableList{}, &void_type,
+      create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
   mod.AddFunction(func);
 
   ASSERT_TRUE(gen.Generate()) << gen.error();
diff --git a/src/writer/spirv/builder_call_test.cc b/src/writer/spirv/builder_call_test.cc
index 2027617..b0c3b82 100644
--- a/src/writer/spirv/builder_call_test.cc
+++ b/src/writer/spirv/builder_call_test.cc
@@ -52,9 +52,12 @@
   body->append(create<ast::ReturnStatement>(create<ast::BinaryExpression>(
       ast::BinaryOp::kAdd, create<ast::IdentifierExpression>("a"),
       create<ast::IdentifierExpression>("b"))));
-  ast::Function a_func("a_func", func_params, &f32, body);
+  ast::Function a_func(Source{}, "a_func", func_params, &f32, body,
+                       ast::FunctionDecorationList{});
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "main", {}, &void_type,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ast::ExpressionList call_params;
   call_params.push_back(create<ast::ScalarConstructorExpression>(
@@ -114,9 +117,12 @@
       ast::BinaryOp::kAdd, create<ast::IdentifierExpression>("a"),
       create<ast::IdentifierExpression>("b"))));
 
-  ast::Function a_func("a_func", func_params, &void_type, body);
+  ast::Function a_func(Source{}, "a_func", func_params, &void_type, body,
+                       ast::FunctionDecorationList{});
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "main", {}, &void_type,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ast::ExpressionList call_params;
   call_params.push_back(create<ast::ScalarConstructorExpression>(
diff --git a/src/writer/spirv/builder_function_decoration_test.cc b/src/writer/spirv/builder_function_decoration_test.cc
index 4eb517a..2aa4cc5 100644
--- a/src/writer/spirv/builder_function_decoration_test.cc
+++ b/src/writer/spirv/builder_function_decoration_test.cc
@@ -41,9 +41,11 @@
 TEST_F(BuilderTest, FunctionDecoration_Stage) {
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  ast::Function func(
+      Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
   EXPECT_EQ(DumpInstructions(b.entry_points()),
@@ -65,8 +67,11 @@
 
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(create<ast::StageDecoration>(params.stage, Source{}));
+  ast::Function func(Source{}, "main", {}, &void_type,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{
+                         create<ast::StageDecoration>(params.stage, Source{}),
+                     });
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -91,9 +96,12 @@
   ast::type::F32 f32;
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  ast::Function func(
+      Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
+
   auto* v_in = create<ast::Variable>("my_in", ast::StorageClass::kInput, &f32);
   auto* v_out =
       create<ast::Variable>("my_out", ast::StorageClass::kOutput, &f32);
@@ -134,9 +142,11 @@
   ast::type::F32 f32;
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
+  ast::Function func(
+      Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}),
+      });
 
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::AssignmentStatement>(
@@ -196,9 +206,11 @@
 TEST_F(BuilderTest, FunctionDecoration_ExecutionMode_Fragment_OriginUpperLeft) {
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  ast::Function func(
+      Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   ASSERT_TRUE(b.GenerateExecutionModes(&func, 3)) << b.error();
   EXPECT_EQ(DumpInstructions(b.execution_modes()),
@@ -209,9 +221,11 @@
 TEST_F(BuilderTest, FunctionDecoration_WorkgroupSize_Default) {
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  ast::Function func(
+      Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   ASSERT_TRUE(b.GenerateExecutionModes(&func, 3)) << b.error();
   EXPECT_EQ(DumpInstructions(b.execution_modes()),
@@ -222,10 +236,12 @@
 TEST_F(BuilderTest, FunctionDecoration_WorkgroupSize) {
   ast::type::Void void_type;
 
-  ast::Function func("main", {}, &void_type, create<ast::BlockStatement>());
-  func.add_decoration(create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}));
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  ast::Function func(
+      Source{}, "main", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}),
+          create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}),
+      });
 
   ASSERT_TRUE(b.GenerateExecutionModes(&func, 3)) << b.error();
   EXPECT_EQ(DumpInstructions(b.execution_modes()),
@@ -236,13 +252,17 @@
 TEST_F(BuilderTest, FunctionDecoration_ExecutionMode_MultipleFragment) {
   ast::type::Void void_type;
 
-  ast::Function func1("main1", {}, &void_type, create<ast::BlockStatement>());
-  func1.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  ast::Function func1(
+      Source{}, "main1", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
-  ast::Function func2("main2", {}, &void_type, create<ast::BlockStatement>());
-  func2.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  ast::Function func2(
+      Source{}, "main2", {}, &void_type, create<ast::BlockStatement>(),
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   ASSERT_TRUE(b.GenerateFunction(&func1)) << b.error();
   ASSERT_TRUE(b.GenerateFunction(&func2)) << b.error();
diff --git a/src/writer/spirv/builder_function_test.cc b/src/writer/spirv/builder_function_test.cc
index cc30814..6121675 100644
--- a/src/writer/spirv/builder_function_test.cc
+++ b/src/writer/spirv/builder_function_test.cc
@@ -48,7 +48,9 @@
 
 TEST_F(BuilderTest, Function_Empty) {
   ast::type::Void void_type;
-  ast::Function func("a_func", {}, &void_type, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &void_type,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func));
   EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
@@ -67,7 +69,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
 
-  ast::Function func("a_func", {}, &void_type, body);
+  ast::Function func(Source{}, "a_func", {}, &void_type, body,
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func));
   EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
@@ -92,7 +95,8 @@
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("a")));
   ASSERT_TRUE(td.DetermineResultType(body)) << td.error();
 
-  ast::Function func("a_func", {}, &void_type, body);
+  ast::Function func(Source{}, "a_func", {}, &void_type, body,
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(var_a)) << b.error();
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@@ -118,7 +122,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::DiscardStatement>());
 
-  ast::Function func("a_func", {}, &void_type, body);
+  ast::Function func(Source{}, "a_func", {}, &void_type, body,
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func));
   EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
@@ -147,7 +152,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(
       create<ast::ReturnStatement>(create<ast::IdentifierExpression>("a")));
-  ast::Function func("a_func", params, &f32, body);
+  ast::Function func(Source{}, "a_func", params, &f32, body,
+                     ast::FunctionDecorationList{});
 
   td.RegisterVariableForTesting(func.params()[0]);
   td.RegisterVariableForTesting(func.params()[1]);
@@ -175,7 +181,8 @@
   auto* body = create<ast::BlockStatement>();
   body->append(create<ast::ReturnStatement>());
 
-  ast::Function func("a_func", {}, &void_type, body);
+  ast::Function func(Source{}, "a_func", {}, &void_type, body,
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func));
   EXPECT_EQ(DumpBuilder(b), R"(OpName %3 "a_func"
@@ -190,7 +197,9 @@
 
 TEST_F(BuilderTest, FunctionType) {
   ast::type::Void void_type;
-  ast::Function func("a_func", {}, &void_type, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &void_type,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func));
   EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeVoid
@@ -200,8 +209,12 @@
 
 TEST_F(BuilderTest, FunctionType_DeDuplicate) {
   ast::type::Void void_type;
-  ast::Function func1("a_func", {}, &void_type, create<ast::BlockStatement>());
-  ast::Function func2("b_func", {}, &void_type, create<ast::BlockStatement>());
+  ast::Function func1(Source{}, "a_func", {}, &void_type,
+                      create<ast::BlockStatement>(),
+                      ast::FunctionDecorationList{});
+  ast::Function func2(Source{}, "b_func", {}, &void_type,
+                      create<ast::BlockStatement>(),
+                      ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func1));
   ASSERT_TRUE(b.GenerateFunction(&func2));
@@ -267,9 +280,12 @@
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
 
-    auto* func = create<ast::Function>("a", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "a", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod->AddFunction(func);
   }
@@ -285,9 +301,12 @@
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
 
-    auto* func = create<ast::Function>("b", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "b", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod->AddFunction(func);
   }
diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc
index b42252e..48be756 100644
--- a/src/writer/spirv/builder_intrinsic_test.cc
+++ b/src/writer/spirv/builder_intrinsic_test.cc
@@ -638,7 +638,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
@@ -670,7 +672,9 @@
   auto expr = Call(param.name, 1.0f);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -696,7 +700,9 @@
   auto expr = Call(param.name, vec2<f32>(1.0f, 1.0f));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -748,7 +754,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -771,7 +779,9 @@
   auto expr = Call("length", vec2<f32>(1.0f, 1.0f));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -796,7 +806,9 @@
   auto expr = Call("normalize", vec2<f32>(1.0f, 1.0f));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -826,7 +838,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -853,7 +867,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -888,7 +904,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -912,7 +930,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -939,7 +959,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -968,7 +990,9 @@
   auto expr = Call(param.name, 1.0f, 1.0f, 1.0f);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -996,7 +1020,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1035,7 +1061,9 @@
   auto expr = Call(param.name, 1);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1061,7 +1089,9 @@
   auto expr = Call(param.name, vec2<i32>(1, 1));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1094,7 +1124,9 @@
   auto expr = Call(param.name, 1u);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1120,7 +1152,9 @@
   auto expr = Call(param.name, vec2<u32>(1u, 1u));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1153,7 +1187,9 @@
   auto expr = Call(param.name, 1, 1);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1179,7 +1215,9 @@
   auto expr = Call(param.name, vec2<i32>(1, 1), vec2<i32>(1, 1));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1213,7 +1251,9 @@
   auto expr = Call(param.name, 1u, 1u);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1239,7 +1279,9 @@
   auto expr = Call(param.name, vec2<u32>(1u, 1u), vec2<u32>(1u, 1u));
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1273,7 +1315,9 @@
   auto expr = Call(param.name, 1, 1, 1);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1301,7 +1345,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1334,7 +1380,9 @@
   auto expr = Call(param.name, 1u, 1u, 1u);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1362,7 +1410,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1393,7 +1443,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
 
@@ -1435,7 +1487,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
@@ -1473,7 +1527,9 @@
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
@@ -1517,7 +1573,9 @@
   auto expr = Call("arrayLength", "ptr_var");
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, ty.void_, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, ty.void_,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
diff --git a/src/writer/spirv/builder_switch_test.cc b/src/writer/spirv/builder_switch_test.cc
index aeb8724..e95cd6c 100644
--- a/src/writer/spirv/builder_switch_test.cc
+++ b/src/writer/spirv/builder_switch_test.cc
@@ -107,7 +107,9 @@
   td.RegisterVariableForTesting(a);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, &i32, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &i32,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
@@ -171,7 +173,9 @@
   td.RegisterVariableForTesting(a);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, &i32, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &i32,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
@@ -254,7 +258,9 @@
   td.RegisterVariableForTesting(a);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, &i32, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &i32,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
@@ -346,7 +352,9 @@
   td.RegisterVariableForTesting(a);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, &i32, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &i32,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
@@ -417,7 +425,9 @@
   td.RegisterVariableForTesting(a);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, &i32, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &i32,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
@@ -469,7 +479,9 @@
   td.RegisterVariableForTesting(a);
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
 
-  ast::Function func("a_func", {}, &i32, create<ast::BlockStatement>());
+  ast::Function func(Source{}, "a_func", {}, &i32,
+                     create<ast::BlockStatement>(),
+                     ast::FunctionDecorationList{});
 
   ASSERT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
   ASSERT_TRUE(b.GenerateGlobalVariable(a)) << b.error();
diff --git a/src/writer/wgsl/generator_impl_function_test.cc b/src/writer/wgsl/generator_impl_function_test.cc
index f2ae9ad..bb443c9 100644
--- a/src/writer/wgsl/generator_impl_function_test.cc
+++ b/src/writer/wgsl/generator_impl_function_test.cc
@@ -47,7 +47,8 @@
   body->append(create<ast::ReturnStatement>());
 
   ast::type::Void void_type;
-  ast::Function func("my_func", {}, &void_type, body);
+  ast::Function func(Source{}, "my_func", {}, &void_type, body,
+                     ast::FunctionDecorationList{});
 
   gen.increment_indent();
 
@@ -71,7 +72,8 @@
   params.push_back(create<ast::Variable>("b", ast::StorageClass::kNone, &i32));
 
   ast::type::Void void_type;
-  ast::Function func("my_func", params, &void_type, body);
+  ast::Function func(Source{}, "my_func", params, &void_type, body,
+                     ast::FunctionDecorationList{});
 
   gen.increment_indent();
 
@@ -89,8 +91,10 @@
   body->append(create<ast::ReturnStatement>());
 
   ast::type::Void void_type;
-  ast::Function func("my_func", {}, &void_type, body);
-  func.add_decoration(create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}));
+  ast::Function func(Source{}, "my_func", {}, &void_type, body,
+                     ast::FunctionDecorationList{
+                         create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}),
+                     });
 
   gen.increment_indent();
 
@@ -109,9 +113,11 @@
   body->append(create<ast::ReturnStatement>());
 
   ast::type::Void void_type;
-  ast::Function func("my_func", {}, &void_type, body);
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
+  ast::Function func(
+      Source{}, "my_func", {}, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+      });
 
   gen.increment_indent();
 
@@ -130,10 +136,12 @@
   body->append(create<ast::ReturnStatement>());
 
   ast::type::Void void_type;
-  ast::Function func("my_func", {}, &void_type, body);
-  func.add_decoration(
-      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
-  func.add_decoration(create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}));
+  ast::Function func(
+      Source{}, "my_func", {}, &void_type, body,
+      ast::FunctionDecorationList{
+          create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}),
+          create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}),
+      });
 
   gen.increment_indent();
 
@@ -205,9 +213,12 @@
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
 
-    auto* func = create<ast::Function>("a", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "a", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod.AddFunction(func);
   }
@@ -223,9 +234,12 @@
     body->append(create<ast::VariableDeclStatement>(var));
     body->append(create<ast::ReturnStatement>());
 
-    auto* func = create<ast::Function>("b", params, &void_type, body);
-    func->add_decoration(
-        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+    auto* func =
+        create<ast::Function>(Source{}, "b", params, &void_type, body,
+                              ast::FunctionDecorationList{
+                                  create<ast::StageDecoration>(
+                                      ast::PipelineStage::kCompute, Source{}),
+                              });
 
     mod.AddFunction(func);
   }
diff --git a/src/writer/wgsl/generator_impl_test.cc b/src/writer/wgsl/generator_impl_test.cc
index a088017..5343153 100644
--- a/src/writer/wgsl/generator_impl_test.cc
+++ b/src/writer/wgsl/generator_impl_test.cc
@@ -32,9 +32,9 @@
 TEST_F(WgslGeneratorImplTest, Generate) {
   ast::type::Void void_type;
 
-  mod.AddFunction(create<ast::Function>("my_func", ast::VariableList{},
-                                        &void_type,
-                                        create<ast::BlockStatement>()));
+  mod.AddFunction(create<ast::Function>(
+      Source{}, "my_func", ast::VariableList{}, &void_type,
+      create<ast::BlockStatement>(), ast::FunctionDecorationList{}));
 
   ASSERT_TRUE(gen.Generate(mod)) << gen.error();
   EXPECT_EQ(gen.result(), R"(fn my_func() -> void {