Cloning: move arguments to create() into temporary locals

In C++ argument evaluation order is undefined. MSVC and Clang evaluate these in different orders, leading to hilarity when writing tests that expect a deterministic ordering.

Pull out all the argument expressions to create() in the clone functions so a cloned program is deterministic in its ordering between compilers.

Change-Id: I8e2de31398960c480ce7ee1dfaac4f67652d2dbc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/41544
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: Ben Clayton <bclayton@google.com>
diff --git a/src/ast/access_decoration.cc b/src/ast/access_decoration.cc
index 976ffe2..1d59be5 100644
--- a/src/ast/access_decoration.cc
+++ b/src/ast/access_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 AccessDecoration* AccessDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<AccessDecoration>(ctx->Clone(source()), value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<AccessDecoration>(src, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/array_accessor_expression.cc b/src/ast/array_accessor_expression.cc
index b8855b0..c0d7c09 100644
--- a/src/ast/array_accessor_expression.cc
+++ b/src/ast/array_accessor_expression.cc
@@ -34,8 +34,11 @@
 
 ArrayAccessorExpression* ArrayAccessorExpression::Clone(
     CloneContext* ctx) const {
-  return ctx->dst->create<ArrayAccessorExpression>(
-      ctx->Clone(source()), ctx->Clone(array_), ctx->Clone(idx_expr_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* arr = ctx->Clone(array_);
+  auto* idx = ctx->Clone(idx_expr_);
+  return ctx->dst->create<ArrayAccessorExpression>(src, arr, idx);
 }
 
 bool ArrayAccessorExpression::IsValid() const {
diff --git a/src/ast/assignment_statement.cc b/src/ast/assignment_statement.cc
index aec1d64..9c8787e 100644
--- a/src/ast/assignment_statement.cc
+++ b/src/ast/assignment_statement.cc
@@ -32,8 +32,11 @@
 AssignmentStatement::~AssignmentStatement() = default;
 
 AssignmentStatement* AssignmentStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<AssignmentStatement>(
-      ctx->Clone(source()), ctx->Clone(lhs_), ctx->Clone(rhs_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* l = ctx->Clone(lhs_);
+  auto* r = ctx->Clone(rhs_);
+  return ctx->dst->create<AssignmentStatement>(src, l, r);
 }
 
 bool AssignmentStatement::IsValid() const {
diff --git a/src/ast/binary_expression.cc b/src/ast/binary_expression.cc
index c1fc0d6..980d035 100644
--- a/src/ast/binary_expression.cc
+++ b/src/ast/binary_expression.cc
@@ -33,8 +33,11 @@
 BinaryExpression::~BinaryExpression() = default;
 
 BinaryExpression* BinaryExpression::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BinaryExpression>(ctx->Clone(source()), op_,
-                                            ctx->Clone(lhs_), ctx->Clone(rhs_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* l = ctx->Clone(lhs_);
+  auto* r = ctx->Clone(rhs_);
+  return ctx->dst->create<BinaryExpression>(src, op_, l, r);
 }
 
 bool BinaryExpression::IsValid() const {
diff --git a/src/ast/binding_decoration.cc b/src/ast/binding_decoration.cc
index a8714dc..b15f023 100644
--- a/src/ast/binding_decoration.cc
+++ b/src/ast/binding_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 BindingDecoration* BindingDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BindingDecoration>(ctx->Clone(source()), value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<BindingDecoration>(src, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/bitcast_expression.cc b/src/ast/bitcast_expression.cc
index df28119..eecfe7e 100644
--- a/src/ast/bitcast_expression.cc
+++ b/src/ast/bitcast_expression.cc
@@ -31,8 +31,11 @@
 BitcastExpression::~BitcastExpression() = default;
 
 BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BitcastExpression>(
-      ctx->Clone(source()), ctx->Clone(type_), ctx->Clone(expr_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type_);
+  auto* e = ctx->Clone(expr_);
+  return ctx->dst->create<BitcastExpression>(src, ty, e);
 }
 
 bool BitcastExpression::IsValid() const {
diff --git a/src/ast/block_statement.cc b/src/ast/block_statement.cc
index 6e4b3f2..09ff97d 100644
--- a/src/ast/block_statement.cc
+++ b/src/ast/block_statement.cc
@@ -31,8 +31,10 @@
 BlockStatement::~BlockStatement() = default;
 
 BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BlockStatement>(ctx->Clone(source()),
-                                          ctx->Clone(statements_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto stmts = ctx->Clone(statements_);
+  return ctx->dst->create<BlockStatement>(src, stmts);
 }
 
 bool BlockStatement::IsValid() const {
diff --git a/src/ast/bool_literal.cc b/src/ast/bool_literal.cc
index 9a9f180..1952456 100644
--- a/src/ast/bool_literal.cc
+++ b/src/ast/bool_literal.cc
@@ -36,8 +36,10 @@
 }
 
 BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BoolLiteral>(ctx->Clone(source()), ctx->Clone(type()),
-                                       value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<BoolLiteral>(src, ty, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/break_statement.cc b/src/ast/break_statement.cc
index 15a8e1c..59de3d4 100644
--- a/src/ast/break_statement.cc
+++ b/src/ast/break_statement.cc
@@ -29,7 +29,9 @@
 BreakStatement::~BreakStatement() = default;
 
 BreakStatement* BreakStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BreakStatement>(ctx->Clone(source()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<BreakStatement>(src);
 }
 
 bool BreakStatement::IsValid() const {
diff --git a/src/ast/builtin_decoration.cc b/src/ast/builtin_decoration.cc
index e275752..02300b6 100644
--- a/src/ast/builtin_decoration.cc
+++ b/src/ast/builtin_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 BuiltinDecoration* BuiltinDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<BuiltinDecoration>(ctx->Clone(source()), builtin_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<BuiltinDecoration>(src, builtin_);
 }
 
 }  // namespace ast
diff --git a/src/ast/call_expression.cc b/src/ast/call_expression.cc
index a54f9a7..d6a2c5a 100644
--- a/src/ast/call_expression.cc
+++ b/src/ast/call_expression.cc
@@ -32,8 +32,11 @@
 CallExpression::~CallExpression() = default;
 
 CallExpression* CallExpression::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<CallExpression>(
-      ctx->Clone(source()), ctx->Clone(func_), ctx->Clone(params_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* fn = ctx->Clone(func_);
+  auto p = ctx->Clone(params_);
+  return ctx->dst->create<CallExpression>(src, fn, p);
 }
 
 bool CallExpression::IsValid() const {
diff --git a/src/ast/call_statement.cc b/src/ast/call_statement.cc
index 1e48538..97bc730 100644
--- a/src/ast/call_statement.cc
+++ b/src/ast/call_statement.cc
@@ -31,8 +31,10 @@
 CallStatement::~CallStatement() = default;
 
 CallStatement* CallStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<CallStatement>(ctx->Clone(source()),
-                                         ctx->Clone(call_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* call = ctx->Clone(call_);
+  return ctx->dst->create<CallStatement>(src, call);
 }
 
 bool CallStatement::IsValid() const {
diff --git a/src/ast/case_statement.cc b/src/ast/case_statement.cc
index 5f5934d..a467999 100644
--- a/src/ast/case_statement.cc
+++ b/src/ast/case_statement.cc
@@ -32,8 +32,11 @@
 CaseStatement::~CaseStatement() = default;
 
 CaseStatement* CaseStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<CaseStatement>(
-      ctx->Clone(source()), ctx->Clone(selectors_), ctx->Clone(body_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto sel = ctx->Clone(selectors_);
+  auto* b = ctx->Clone(body_);
+  return ctx->dst->create<CaseStatement>(src, sel, b);
 }
 
 bool CaseStatement::IsValid() const {
diff --git a/src/ast/constant_id_decoration.cc b/src/ast/constant_id_decoration.cc
index fec8fe8..1fa9987 100644
--- a/src/ast/constant_id_decoration.cc
+++ b/src/ast/constant_id_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 ConstantIdDecoration* ConstantIdDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<ConstantIdDecoration>(ctx->Clone(source()), value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<ConstantIdDecoration>(src, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/continue_statement.cc b/src/ast/continue_statement.cc
index 3b066a4..5d3d7cb 100644
--- a/src/ast/continue_statement.cc
+++ b/src/ast/continue_statement.cc
@@ -29,7 +29,9 @@
 ContinueStatement::~ContinueStatement() = default;
 
 ContinueStatement* ContinueStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<ContinueStatement>(ctx->Clone(source()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<ContinueStatement>(src);
 }
 
 bool ContinueStatement::IsValid() const {
diff --git a/src/ast/discard_statement.cc b/src/ast/discard_statement.cc
index ec2bf65..9deed12 100644
--- a/src/ast/discard_statement.cc
+++ b/src/ast/discard_statement.cc
@@ -29,7 +29,9 @@
 DiscardStatement::~DiscardStatement() = default;
 
 DiscardStatement* DiscardStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<DiscardStatement>(ctx->Clone(source()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<DiscardStatement>(src);
 }
 
 bool DiscardStatement::IsValid() const {
diff --git a/src/ast/else_statement.cc b/src/ast/else_statement.cc
index 30e18a6..a80fe36 100644
--- a/src/ast/else_statement.cc
+++ b/src/ast/else_statement.cc
@@ -32,8 +32,11 @@
 ElseStatement::~ElseStatement() = default;
 
 ElseStatement* ElseStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<ElseStatement>(
-      ctx->Clone(source()), ctx->Clone(condition_), ctx->Clone(body_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* cond = ctx->Clone(condition_);
+  auto* b = ctx->Clone(body_);
+  return ctx->dst->create<ElseStatement>(src, cond, b);
 }
 
 bool ElseStatement::IsValid() const {
diff --git a/src/ast/fallthrough_statement.cc b/src/ast/fallthrough_statement.cc
index dcdc26a..ce1e715 100644
--- a/src/ast/fallthrough_statement.cc
+++ b/src/ast/fallthrough_statement.cc
@@ -30,7 +30,9 @@
 FallthroughStatement::~FallthroughStatement() = default;
 
 FallthroughStatement* FallthroughStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<FallthroughStatement>(ctx->Clone(source()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<FallthroughStatement>(src);
 }
 
 bool FallthroughStatement::IsValid() const {
diff --git a/src/ast/float_literal.cc b/src/ast/float_literal.cc
index f7b54f4..a99bec2 100644
--- a/src/ast/float_literal.cc
+++ b/src/ast/float_literal.cc
@@ -43,8 +43,10 @@
 }
 
 FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<FloatLiteral>(ctx->Clone(source()),
-                                        ctx->Clone(type()), value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<FloatLiteral>(src, ty, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/function.cc b/src/ast/function.cc
index a2b5ef7..f93e1d6 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -70,9 +70,14 @@
 }
 
 Function* Function::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Function>(
-      ctx->Clone(source()), ctx->Clone(symbol()), ctx->Clone(params_),
-      ctx->Clone(return_type_), ctx->Clone(body_), ctx->Clone(decorations_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto sym = ctx->Clone(symbol());
+  auto p = ctx->Clone(params_);
+  auto* ret = ctx->Clone(return_type_);
+  auto* b = ctx->Clone(body_);
+  auto decos = ctx->Clone(decorations_);
+  return ctx->dst->create<Function>(src, sym, p, ret, b, decos);
 }
 
 bool Function::IsValid() const {
diff --git a/src/ast/group_decoration.cc b/src/ast/group_decoration.cc
index 5c8171d..08a4107 100644
--- a/src/ast/group_decoration.cc
+++ b/src/ast/group_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 GroupDecoration* GroupDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<GroupDecoration>(ctx->Clone(source()), value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<GroupDecoration>(src, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/identifier_expression.cc b/src/ast/identifier_expression.cc
index ba05e64..c8c9fd1 100644
--- a/src/ast/identifier_expression.cc
+++ b/src/ast/identifier_expression.cc
@@ -30,8 +30,10 @@
 IdentifierExpression::~IdentifierExpression() = default;
 
 IdentifierExpression* IdentifierExpression::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<IdentifierExpression>(ctx->Clone(source()),
-                                                ctx->Clone(symbol()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto sym = ctx->Clone(symbol());
+  return ctx->dst->create<IdentifierExpression>(src, sym);
 }
 
 bool IdentifierExpression::IsValid() const {
diff --git a/src/ast/if_statement.cc b/src/ast/if_statement.cc
index 0b018ef..5ad49aa 100644
--- a/src/ast/if_statement.cc
+++ b/src/ast/if_statement.cc
@@ -37,10 +37,12 @@
 IfStatement::~IfStatement() = default;
 
 IfStatement* IfStatement::Clone(CloneContext* ctx) const {
-  auto* cloned = ctx->dst->create<IfStatement>(
-      ctx->Clone(source()), ctx->Clone(condition_), ctx->Clone(body_),
-      ctx->Clone(else_statements_));
-  return cloned;
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* cond = ctx->Clone(condition_);
+  auto* b = ctx->Clone(body_);
+  auto el = ctx->Clone(else_statements_);
+  return ctx->dst->create<IfStatement>(src, cond, b, el);
 }
 
 bool IfStatement::IsValid() const {
diff --git a/src/ast/location_decoration.cc b/src/ast/location_decoration.cc
index 8e25036..4052819 100644
--- a/src/ast/location_decoration.cc
+++ b/src/ast/location_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 LocationDecoration* LocationDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<LocationDecoration>(ctx->Clone(source()), value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<LocationDecoration>(src, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/loop_statement.cc b/src/ast/loop_statement.cc
index 74cb698..9616499 100644
--- a/src/ast/loop_statement.cc
+++ b/src/ast/loop_statement.cc
@@ -32,8 +32,11 @@
 LoopStatement::~LoopStatement() = default;
 
 LoopStatement* LoopStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<LoopStatement>(
-      ctx->Clone(source()), ctx->Clone(body_), ctx->Clone(continuing_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* b = ctx->Clone(body_);
+  auto* cont = ctx->Clone(continuing_);
+  return ctx->dst->create<LoopStatement>(src, b, cont);
 }
 
 bool LoopStatement::IsValid() const {
diff --git a/src/ast/member_accessor_expression.cc b/src/ast/member_accessor_expression.cc
index e58ad98..be335f4 100644
--- a/src/ast/member_accessor_expression.cc
+++ b/src/ast/member_accessor_expression.cc
@@ -34,8 +34,11 @@
 
 MemberAccessorExpression* MemberAccessorExpression::Clone(
     CloneContext* ctx) const {
-  return ctx->dst->create<MemberAccessorExpression>(
-      ctx->Clone(source()), ctx->Clone(struct_), ctx->Clone(member_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* str = ctx->Clone(structure());
+  auto* mem = ctx->Clone(member());
+  return ctx->dst->create<MemberAccessorExpression>(src, str, mem);
 }
 
 bool MemberAccessorExpression::IsValid() const {
diff --git a/src/ast/null_literal.cc b/src/ast/null_literal.cc
index 835ae29..7ea8476 100644
--- a/src/ast/null_literal.cc
+++ b/src/ast/null_literal.cc
@@ -36,8 +36,10 @@
 }
 
 NullLiteral* NullLiteral::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<NullLiteral>(ctx->Clone(source()),
-                                       ctx->Clone(type()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<NullLiteral>(src, ty);
 }
 
 }  // namespace ast
diff --git a/src/ast/return_statement.cc b/src/ast/return_statement.cc
index 2f85773..49bebbc 100644
--- a/src/ast/return_statement.cc
+++ b/src/ast/return_statement.cc
@@ -33,8 +33,10 @@
 ReturnStatement::~ReturnStatement() = default;
 
 ReturnStatement* ReturnStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<ReturnStatement>(ctx->Clone(source()),
-                                           ctx->Clone(value_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ret = ctx->Clone(value());
+  return ctx->dst->create<ReturnStatement>(src, ret);
 }
 
 bool ReturnStatement::IsValid() const {
diff --git a/src/ast/scalar_constructor_expression.cc b/src/ast/scalar_constructor_expression.cc
index 4c90f19..61cad8f 100644
--- a/src/ast/scalar_constructor_expression.cc
+++ b/src/ast/scalar_constructor_expression.cc
@@ -33,8 +33,10 @@
 
 ScalarConstructorExpression* ScalarConstructorExpression::Clone(
     CloneContext* ctx) const {
-  return ctx->dst->create<ScalarConstructorExpression>(ctx->Clone(source()),
-                                                       ctx->Clone(literal_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* lit = ctx->Clone(literal());
+  return ctx->dst->create<ScalarConstructorExpression>(src, lit);
 }
 
 bool ScalarConstructorExpression::IsValid() const {
diff --git a/src/ast/sint_literal.cc b/src/ast/sint_literal.cc
index 3c946ac..be82a94 100644
--- a/src/ast/sint_literal.cc
+++ b/src/ast/sint_literal.cc
@@ -36,8 +36,10 @@
 }
 
 SintLiteral* SintLiteral::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<SintLiteral>(ctx->Clone(source()), ctx->Clone(type()),
-                                       value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<SintLiteral>(src, ty, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/stage_decoration.cc b/src/ast/stage_decoration.cc
index bd68fe2..bb12dfe 100644
--- a/src/ast/stage_decoration.cc
+++ b/src/ast/stage_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 StageDecoration* StageDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<StageDecoration>(ctx->Clone(source()), stage_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<StageDecoration>(src, stage_);
 }
 
 }  // namespace ast
diff --git a/src/ast/stride_decoration.cc b/src/ast/stride_decoration.cc
index 52f3ef5..282aea6 100644
--- a/src/ast/stride_decoration.cc
+++ b/src/ast/stride_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 StrideDecoration* StrideDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<StrideDecoration>(ctx->Clone(source()), stride_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<StrideDecoration>(src, stride_);
 }
 
 }  // namespace ast
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index 0493e3a..451fc19 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -53,8 +53,11 @@
 }
 
 Struct* Struct::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Struct>(ctx->Clone(source()), ctx->Clone(members_),
-                                  ctx->Clone(decorations_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto mem = ctx->Clone(members());
+  auto decos = ctx->Clone(decorations());
+  return ctx->dst->create<Struct>(src, mem, decos);
 }
 
 bool Struct::IsValid() const {
diff --git a/src/ast/struct_block_decoration.cc b/src/ast/struct_block_decoration.cc
index 5c69f81..87f5121 100644
--- a/src/ast/struct_block_decoration.cc
+++ b/src/ast/struct_block_decoration.cc
@@ -35,7 +35,9 @@
 }
 
 StructBlockDecoration* StructBlockDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<StructBlockDecoration>(ctx->Clone(source()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<StructBlockDecoration>(src);
 }
 
 }  // namespace ast
diff --git a/src/ast/struct_member.cc b/src/ast/struct_member.cc
index b6aa642..9fc39c5 100644
--- a/src/ast/struct_member.cc
+++ b/src/ast/struct_member.cc
@@ -55,9 +55,12 @@
 }
 
 StructMember* StructMember::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<StructMember>(ctx->Clone(source()),
-                                        ctx->Clone(symbol_), ctx->Clone(type_),
-                                        ctx->Clone(decorations_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto sym = ctx->Clone(symbol_);
+  auto* ty = ctx->Clone(type_);
+  auto decos = ctx->Clone(decorations_);
+  return ctx->dst->create<StructMember>(src, sym, ty, decos);
 }
 
 bool StructMember::IsValid() const {
diff --git a/src/ast/struct_member_offset_decoration.cc b/src/ast/struct_member_offset_decoration.cc
index 87f13a6..9444dc5 100644
--- a/src/ast/struct_member_offset_decoration.cc
+++ b/src/ast/struct_member_offset_decoration.cc
@@ -37,8 +37,9 @@
 
 StructMemberOffsetDecoration* StructMemberOffsetDecoration::Clone(
     CloneContext* ctx) const {
-  return ctx->dst->create<StructMemberOffsetDecoration>(ctx->Clone(source()),
-                                                        offset_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<StructMemberOffsetDecoration>(src, offset_);
 }
 
 }  // namespace ast
diff --git a/src/ast/switch_statement.cc b/src/ast/switch_statement.cc
index 89dc22d..67908a8 100644
--- a/src/ast/switch_statement.cc
+++ b/src/ast/switch_statement.cc
@@ -33,8 +33,11 @@
 SwitchStatement::~SwitchStatement() = default;
 
 SwitchStatement* SwitchStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<SwitchStatement>(
-      ctx->Clone(source()), ctx->Clone(condition_), ctx->Clone(body_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* cond = ctx->Clone(condition());
+  auto b = ctx->Clone(body());
+  return ctx->dst->create<SwitchStatement>(src, cond, b);
 }
 
 bool SwitchStatement::IsValid() const {
diff --git a/src/ast/type_constructor_expression.cc b/src/ast/type_constructor_expression.cc
index 532e0d0..778ecca 100644
--- a/src/ast/type_constructor_expression.cc
+++ b/src/ast/type_constructor_expression.cc
@@ -34,8 +34,11 @@
 
 TypeConstructorExpression* TypeConstructorExpression::Clone(
     CloneContext* ctx) const {
-  return ctx->dst->create<TypeConstructorExpression>(
-      ctx->Clone(source()), ctx->Clone(type_), ctx->Clone(values_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type());
+  auto vals = ctx->Clone(values());
+  return ctx->dst->create<TypeConstructorExpression>(src, ty, vals);
 }
 
 bool TypeConstructorExpression::IsValid() const {
diff --git a/src/ast/uint_literal.cc b/src/ast/uint_literal.cc
index e9dd464..d46602b 100644
--- a/src/ast/uint_literal.cc
+++ b/src/ast/uint_literal.cc
@@ -36,8 +36,10 @@
 }
 
 UintLiteral* UintLiteral::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<UintLiteral>(ctx->Clone(source()), ctx->Clone(type()),
-                                       value_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<UintLiteral>(src, ty, value_);
 }
 
 }  // namespace ast
diff --git a/src/ast/unary_op_expression.cc b/src/ast/unary_op_expression.cc
index 495e49a..e803c21 100644
--- a/src/ast/unary_op_expression.cc
+++ b/src/ast/unary_op_expression.cc
@@ -32,8 +32,10 @@
 UnaryOpExpression::~UnaryOpExpression() = default;
 
 UnaryOpExpression* UnaryOpExpression::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<UnaryOpExpression>(ctx->Clone(source()), op_,
-                                             ctx->Clone(expr_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* e = ctx->Clone(expr());
+  return ctx->dst->create<UnaryOpExpression>(src, op_, e);
 }
 
 bool UnaryOpExpression::IsValid() const {
diff --git a/src/ast/variable.cc b/src/ast/variable.cc
index 40056a4..1dd1bfe 100644
--- a/src/ast/variable.cc
+++ b/src/ast/variable.cc
@@ -92,10 +92,13 @@
 }
 
 Variable* Variable::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Variable>(
-      ctx->Clone(source()), ctx->Clone(symbol_), declared_storage_class(),
-      ctx->Clone(type()), is_const_, ctx->Clone(constructor()),
-      ctx->Clone(decorations_));
+  auto src = ctx->Clone(source());
+  auto sym = ctx->Clone(symbol());
+  auto* ty = ctx->Clone(type());
+  auto* ctor = ctx->Clone(constructor());
+  auto decos = ctx->Clone(decorations());
+  return ctx->dst->create<Variable>(src, sym, declared_storage_class(), ty,
+                                    is_const_, ctor, decos);
 }
 
 bool Variable::IsValid() const {
diff --git a/src/ast/variable_decl_statement.cc b/src/ast/variable_decl_statement.cc
index 2dd0a77..cf9c8d7 100644
--- a/src/ast/variable_decl_statement.cc
+++ b/src/ast/variable_decl_statement.cc
@@ -31,8 +31,10 @@
 VariableDeclStatement::~VariableDeclStatement() = default;
 
 VariableDeclStatement* VariableDeclStatement::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<VariableDeclStatement>(ctx->Clone(source()),
-                                                 ctx->Clone(variable_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  auto* var = ctx->Clone(variable());
+  return ctx->dst->create<VariableDeclStatement>(src, var);
 }
 
 bool VariableDeclStatement::IsValid() const {
diff --git a/src/ast/workgroup_decoration.cc b/src/ast/workgroup_decoration.cc
index 0d49f10..8282a7c 100644
--- a/src/ast/workgroup_decoration.cc
+++ b/src/ast/workgroup_decoration.cc
@@ -47,8 +47,9 @@
 }
 
 WorkgroupDecoration* WorkgroupDecoration::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<WorkgroupDecoration>(ctx->Clone(source()), x_, y_,
-                                               z_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(source());
+  return ctx->dst->create<WorkgroupDecoration>(src, x_, y_, z_);
 }
 
 }  // namespace ast
diff --git a/src/transform/bound_array_accessors.cc b/src/transform/bound_array_accessors.cc
index b17a181..72799be 100644
--- a/src/transform/bound_array_accessors.cc
+++ b/src/transform/bound_array_accessors.cc
@@ -120,12 +120,14 @@
       return nullptr;
     }
   } else {
-    new_idx =
-        b.Call("min", b.Construct<u32>(ctx->Clone(old_idx)), b.Expr(size - 1));
+    auto* cloned_idx = ctx->Clone(old_idx);
+    new_idx = b.Call("min", b.Construct<u32>(cloned_idx), b.Expr(size - 1));
   }
 
-  return b.create<ast::ArrayAccessorExpression>(
-      ctx->Clone(expr->source()), ctx->Clone(expr->array()), new_idx);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto src = ctx->Clone(expr->source());
+  auto* arr = ctx->Clone(expr->array());
+  return b.create<ast::ArrayAccessorExpression>(src, arr, new_idx);
 }
 
 }  // namespace transform
diff --git a/src/transform/first_index_offset.cc b/src/transform/first_index_offset.cc
index 4ed52ab..6afd9fd 100644
--- a/src/transform/first_index_offset.cc
+++ b/src/transform/first_index_offset.cc
@@ -67,14 +67,15 @@
 ast::Variable* clone_variable_with_new_name(CloneContext* ctx,
                                             ast::Variable* in,
                                             std::string new_name) {
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto source = ctx->Clone(in->source());
+  auto symbol = ctx->dst->Symbols().Register(new_name);
+  auto* type = ctx->Clone(in->type());
+  auto* constructor = ctx->Clone(in->constructor());
+  auto decorations = ctx->Clone(in->decorations());
   return ctx->dst->create<ast::Variable>(
-      ctx->Clone(in->source()),                // source
-      ctx->dst->Symbols().Register(new_name),  // symbol
-      in->declared_storage_class(),            // declared_storage_class
-      ctx->Clone(in->type()),                  // type
-      in->is_const(),                          // is_const
-      ctx->Clone(in->constructor()),           // constructor
-      ctx->Clone(in->decorations()));          // decorations
+      source, symbol, in->declared_storage_class(), type, in->is_const(),
+      constructor, decorations);
 }
 
 }  // namespace
diff --git a/src/transform/transform.cc b/src/transform/transform.cc
index b0c8db5..c037cdb 100644
--- a/src/transform/transform.cc
+++ b/src/transform/transform.cc
@@ -40,12 +40,16 @@
   for (auto* s : *in->body()) {
     statements.emplace_back(ctx->Clone(s));
   }
-  return ctx->dst->create<ast::Function>(
-      ctx->Clone(in->source()), ctx->Clone(in->symbol()),
-      ctx->Clone(in->params()), ctx->Clone(in->return_type()),
-      ctx->dst->create<ast::BlockStatement>(ctx->Clone(in->body()->source()),
-                                            statements),
-      ctx->Clone(in->decorations()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto source = ctx->Clone(in->source());
+  auto symbol = ctx->Clone(in->symbol());
+  auto params = ctx->Clone(in->params());
+  auto* return_type = ctx->Clone(in->return_type());
+  auto* body = ctx->dst->create<ast::BlockStatement>(
+      ctx->Clone(in->body()->source()), statements);
+  auto decos = ctx->Clone(in->decorations());
+  return ctx->dst->create<ast::Function>(source, symbol, params, return_type,
+                                         body, decos);
 }
 
 }  // namespace transform
diff --git a/src/type/access_control_type.cc b/src/type/access_control_type.cc
index 4d96e89..19e938b 100644
--- a/src/type/access_control_type.cc
+++ b/src/type/access_control_type.cc
@@ -77,7 +77,9 @@
 }
 
 AccessControl* AccessControl::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<AccessControl>(access_, ctx->Clone(subtype_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<AccessControl>(access_, ty);
 }
 
 }  // namespace type
diff --git a/src/type/alias_type.cc b/src/type/alias_type.cc
index 95fffe2..1bb580c 100644
--- a/src/type/alias_type.cc
+++ b/src/type/alias_type.cc
@@ -50,7 +50,10 @@
 }
 
 Alias* Alias::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Alias>(ctx->Clone(symbol()), ctx->Clone(subtype_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto sym = ctx->Clone(symbol());
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<Alias>(sym, ty);
 }
 
 }  // namespace type
diff --git a/src/type/array_type.cc b/src/type/array_type.cc
index 549b88f..aee68fa 100644
--- a/src/type/array_type.cc
+++ b/src/type/array_type.cc
@@ -109,8 +109,10 @@
 }
 
 Array* Array::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Array>(ctx->Clone(subtype_), size_,
-                                 ctx->Clone(decorations()));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  auto decos = ctx->Clone(decorations());
+  return ctx->dst->create<Array>(ty, size_, decos);
 }
 
 }  // namespace type
diff --git a/src/type/matrix_type.cc b/src/type/matrix_type.cc
index c678f4e..0723543 100644
--- a/src/type/matrix_type.cc
+++ b/src/type/matrix_type.cc
@@ -63,7 +63,9 @@
 }
 
 Matrix* Matrix::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Matrix>(ctx->Clone(subtype_), rows_, columns_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<Matrix>(ty, rows_, columns_);
 }
 
 }  // namespace type
diff --git a/src/type/multisampled_texture_type.cc b/src/type/multisampled_texture_type.cc
index f647016..4c0ec25 100644
--- a/src/type/multisampled_texture_type.cc
+++ b/src/type/multisampled_texture_type.cc
@@ -49,7 +49,9 @@
 }
 
 MultisampledTexture* MultisampledTexture::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<MultisampledTexture>(dim(), ctx->Clone(type_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<MultisampledTexture>(dim(), ty);
 }
 
 }  // namespace type
diff --git a/src/type/pointer_type.cc b/src/type/pointer_type.cc
index ec564ec..7dd3649 100644
--- a/src/type/pointer_type.cc
+++ b/src/type/pointer_type.cc
@@ -46,7 +46,9 @@
 Pointer::~Pointer() = default;
 
 Pointer* Pointer::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Pointer>(ctx->Clone(subtype_), storage_class_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<Pointer>(ty, storage_class_);
 }
 
 }  // namespace type
diff --git a/src/type/sampled_texture_type.cc b/src/type/sampled_texture_type.cc
index bd4fb5c..24c0863 100644
--- a/src/type/sampled_texture_type.cc
+++ b/src/type/sampled_texture_type.cc
@@ -47,7 +47,9 @@
 }
 
 SampledTexture* SampledTexture::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<SampledTexture>(dim(), ctx->Clone(type_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<SampledTexture>(dim(), ty);
 }
 
 }  // namespace type
diff --git a/src/type/storage_texture_type.cc b/src/type/storage_texture_type.cc
index 14f86aa..8c25055 100644
--- a/src/type/storage_texture_type.cc
+++ b/src/type/storage_texture_type.cc
@@ -163,8 +163,9 @@
 }
 
 StorageTexture* StorageTexture::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<StorageTexture>(dim(), image_format_,
-                                          ctx->Clone(subtype_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<StorageTexture>(dim(), image_format_, ty);
 }
 
 type::Type* StorageTexture::SubtypeFor(type::ImageFormat format,
diff --git a/src/type/struct_type.cc b/src/type/struct_type.cc
index 05ba4c7..11a8711 100644
--- a/src/type/struct_type.cc
+++ b/src/type/struct_type.cc
@@ -87,7 +87,10 @@
 }
 
 Struct* Struct::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Struct>(ctx->Clone(symbol()), ctx->Clone(struct_));
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto sym = ctx->Clone(symbol());
+  auto* str = ctx->Clone(impl());
+  return ctx->dst->create<Struct>(sym, str);
 }
 
 }  // namespace type
diff --git a/src/type/vector_type.cc b/src/type/vector_type.cc
index 84cdf24..b141a87 100644
--- a/src/type/vector_type.cc
+++ b/src/type/vector_type.cc
@@ -59,7 +59,9 @@
 }
 
 Vector* Vector::Clone(CloneContext* ctx) const {
-  return ctx->dst->create<Vector>(ctx->Clone(subtype_), size_);
+  // Clone arguments outside of create() call to have deterministic ordering
+  auto* ty = ctx->Clone(type());
+  return ctx->dst->create<Vector>(ty, size_);
 }
 
 }  // namespace type