HLSL-IR: add support for clip_distances.

Bug: 364865292
Bug: 358408571
Change-Id: I4713e40f9dba7f31ac14dd9e1f671f0a8cf44dae
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/211814
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Auto-Submit: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/transform/demote_to_helper.cc b/src/tint/lang/core/ir/transform/demote_to_helper.cc
index d903f25..4c2ad12 100644
--- a/src/tint/lang/core/ir/transform/demote_to_helper.cc
+++ b/src/tint/lang/core/ir/transform/demote_to_helper.cc
@@ -217,6 +217,7 @@
     auto result = ValidateAndDumpIfNeeded(ir, "DemoteToHelper transform",
                                           core::ir::Capabilities{
                                               core::ir::Capability::kAllowVectorElementPointer,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/core/ir/transform/direct_variable_access.cc b/src/tint/lang/core/ir/transform/direct_variable_access.cc
index 24a396a..85ace98 100644
--- a/src/tint/lang/core/ir/transform/direct_variable_access.cc
+++ b/src/tint/lang/core/ir/transform/direct_variable_access.cc
@@ -704,7 +704,10 @@
 }  // namespace
 
 Result<SuccessType> DirectVariableAccess(Module& ir, const DirectVariableAccessOptions& options) {
-    auto result = ValidateAndDumpIfNeeded(ir, "DirectVariableAccess transform");
+    auto result = ValidateAndDumpIfNeeded(ir, "DirectVariableAccess transform",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
+                                          });
     if (result != Success) {
         return result;
     }
diff --git a/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc b/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc
index b56cdef..3e7daff 100644
--- a/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc
+++ b/src/tint/lang/core/ir/transform/remove_continue_in_switch.cc
@@ -118,6 +118,7 @@
                                           core::ir::Capabilities{
                                               core::ir::Capability::kAllowVectorElementPointer,
                                               core::ir::Capability::kAllowHandleVarsWithoutBindings,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/core/ir/transform/remove_terminator_args.cc b/src/tint/lang/core/ir/transform/remove_terminator_args.cc
index af50723..9528622 100644
--- a/src/tint/lang/core/ir/transform/remove_terminator_args.cc
+++ b/src/tint/lang/core/ir/transform/remove_terminator_args.cc
@@ -170,6 +170,7 @@
                                               core::ir::Capability::kAllowPointersInStructures,
                                               core::ir::Capability::kAllowVectorElementPointer,
                                               core::ir::Capability::kAllowHandleVarsWithoutBindings,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/core/ir/transform/rename_conflicts.cc b/src/tint/lang/core/ir/transform/rename_conflicts.cc
index 4407ba0..1c168ca 100644
--- a/src/tint/lang/core/ir/transform/rename_conflicts.cc
+++ b/src/tint/lang/core/ir/transform/rename_conflicts.cc
@@ -299,6 +299,7 @@
                                               core::ir::Capability::kAllowPointersInStructures,
                                               core::ir::Capability::kAllowVectorElementPointer,
                                               core::ir::Capability::kAllowHandleVarsWithoutBindings,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/core/ir/transform/shader_io.cc b/src/tint/lang/core/ir/transform/shader_io.cc
index 4e18bba..3d7cc83 100644
--- a/src/tint/lang/core/ir/transform/shader_io.cc
+++ b/src/tint/lang/core/ir/transform/shader_io.cc
@@ -201,7 +201,8 @@
                     // Strip interpolation on non-vertex outputs
                     attributes.interpolation = {};
                 }
-                backend->AddOutput(ir.symbols.Register(name), member->Type(), attributes);
+                backend->AddOutput(ir.symbols.Register(name), member->Type(),
+                                   std::move(attributes));
             }
         } else {
             // Pull out the IO attributes and remove them from the original function.
diff --git a/src/tint/lang/core/ir/transform/value_to_let.cc b/src/tint/lang/core/ir/transform/value_to_let.cc
index 3360baf..457ca79 100644
--- a/src/tint/lang/core/ir/transform/value_to_let.cc
+++ b/src/tint/lang/core/ir/transform/value_to_let.cc
@@ -263,6 +263,7 @@
                                               core::ir::Capability::kAllowPointersInStructures,
                                               core::ir::Capability::kAllowVectorElementPointer,
                                               core::ir::Capability::kAllowHandleVarsWithoutBindings,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc b/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc
index 313e1b0..57eebab 100644
--- a/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc
+++ b/src/tint/lang/core/ir/transform/vectorize_scalar_matrix_constructors.cc
@@ -98,6 +98,7 @@
                                           core::ir::Capabilities{
                                               core::ir::Capability::kAllowVectorElementPointer,
                                               core::ir::Capability::kAllowHandleVarsWithoutBindings,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 9d3ff9d..2c3c9dd 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -324,18 +324,6 @@
     /* type_error */ "__point_size must be a f32",
 };
 
-constexpr BuiltinChecker kClipDistancesChecker{
-    /* name */ "clip_distances",
-    /* stages */ EnumSet<Function::PipelineStage>(Function::PipelineStage::kVertex),
-    /* direction */ BuiltinChecker::IODirection::kOutput,
-    /* type_check */
-    [](const core::type::Type* ty) -> bool {
-        auto elems = ty->Elements();
-        return elems.type && elems.type->Is<core::type::F32>() && elems.count <= 8;
-    },
-    /* type_error */ "clip_distances must be an array<f32, N>, where N <= 8",
-};
-
 constexpr BuiltinChecker kFragDepthChecker{
     /* name */ "frag_depth",
     /* stages */ EnumSet<Function::PipelineStage>(Function::PipelineStage::kFragment),
@@ -453,8 +441,6 @@
     switch (builtin) {
         case BuiltinValue::kPointSize:
             return kPointSizeChecker;
-        case BuiltinValue::kClipDistances:
-            return kClipDistancesChecker;
         case BuiltinValue::kFragDepth:
             return kFragDepthChecker;
         case BuiltinValue::kFrontFacing:
@@ -535,6 +521,40 @@
     return Success;
 }
 
+/// Validates the basic spec rules for @builtin(clip_distance) usage
+/// @param stage the shader stage the builtin is being used
+/// @param is_input the IO direction of usage, true if input, false if output
+/// @param capabilities the optional capabilities that are allowed
+/// @param ty the data type being decorated by the builtin
+/// @returns Success if a valid usage, or reason for invalidity in Failure
+Result<SuccessType, std::string> ValidateBuiltinClipDistances(Function::PipelineStage stage,
+                                                              bool is_input,
+                                                              const Capabilities& capabilities,
+                                                              const core::type::Type* ty) {
+    if (stage != Function::PipelineStage::kVertex) {
+        return std::string("clip_distances must be used in a vertex shader entry point");
+    }
+
+    if (is_input) {
+        return std::string("clip_distances must be an output of a shader entry point");
+    }
+
+    auto is_valid_array = [&] {
+        const auto elems = ty->Elements();
+        return elems.type && elems.type->Is<core::type::F32>() && elems.count <= 8;
+    };
+
+    if (capabilities.Contains(Capability::kAllowClipDistancesOnF32)) {
+        if (!ty->Is<core::type::F32>() && !is_valid_array()) {
+            return std::string("clip_distances must be an f32 or an array<f32, N>, where N <= 8");
+        }
+    } else if (!is_valid_array()) {
+        return std::string("clip_distances must be an array<f32, N>, where N <= 8");
+    }
+
+    return Success;
+}
+
 /// Validates the basic spec rules for builtin usage
 /// @param builtin the builtin to test
 /// @param stage the shader stage the builtin is being used
@@ -544,6 +564,7 @@
 Result<SuccessType, std::string> ValidateBuiltIn(BuiltinValue builtin,
                                                  Function::PipelineStage stage,
                                                  bool is_input,
+                                                 const Capabilities& capabilities,
                                                  const core::type::Type* ty) {
     // This is not an entry point function, either it is dead code and thus never called, or any
     // issues will be detected when validating the calling entry point.
@@ -558,8 +579,10 @@
             return ValidatePositionBuiltIn(stage, is_input, ty);
         case BuiltinValue::kSampleMask:
             return ValidateSampleMaskBuiltIn(stage, ty);
-        default: {
-        }
+        case BuiltinValue::kClipDistances:
+            return ValidateBuiltinClipDistances(stage, is_input, capabilities, ty);
+        default:
+            break;
     }
 
     const auto& checker = BuiltinCheckerFor(builtin);
@@ -850,8 +873,8 @@
             if (!attr.builtin.has_value()) {
                 return;
             }
-            auto result =
-                ValidateBuiltIn(attr.builtin.value(), param->Function()->Stage(), true, ty);
+            auto result = ValidateBuiltIn(attr.builtin.value(), param->Function()->Stage(), true,
+                                          capabilities_, ty);
             if (result != Success) {
                 AddError(param) << err << result.Failure();
             }
@@ -864,7 +887,8 @@
             if (!attr.builtin.has_value()) {
                 return;
             }
-            auto result = ValidateBuiltIn(attr.builtin.value(), func->Stage(), false, ty);
+            auto result =
+                ValidateBuiltIn(attr.builtin.value(), func->Stage(), false, capabilities_, ty);
             if (result != Success) {
                 AddError(func) << err << result.Failure();
             }
diff --git a/src/tint/lang/core/ir/validator.h b/src/tint/lang/core/ir/validator.h
index 9ae5673..4681e03 100644
--- a/src/tint/lang/core/ir/validator.h
+++ b/src/tint/lang/core/ir/validator.h
@@ -54,6 +54,8 @@
     kAllowPointersInStructures,
     /// Allows handle vars to not have binding points
     kAllowHandleVarsWithoutBindings,
+    /// Allows ClipDistances on f32 parameters
+    kAllowClipDistancesOnF32,
 };
 
 /// Capabilities is a set of Capability
diff --git a/src/tint/lang/hlsl/writer/printer/printer.cc b/src/tint/lang/hlsl/writer/printer/printer.cc
index 4a42a82..05d3209 100644
--- a/src/tint/lang/hlsl/writer/printer/printer.cc
+++ b/src/tint/lang/hlsl/writer/printer/printer.cc
@@ -158,6 +158,7 @@
         core::ir::Capabilities capabilities{
             core::ir::Capability::kAllowModuleScopeLets,
             core::ir::Capability::kAllowVectorElementPointer,
+            core::ir::Capability::kAllowClipDistancesOnF32,
         };
         auto valid = core::ir::ValidateAndDumpIfNeeded(ir_, "HLSL writer", capabilities);
         if (valid != Success) {
@@ -1471,6 +1472,7 @@
         TextBuffer str_buf;
         Line(&str_buf) << "struct " << StructName(str) << " {";
         {
+            int which_clip_distance = 0;
             const ScopedIndent si(&str_buf);
             for (auto* mem : str->Members()) {
                 auto mem_name = mem->Name().Name();
@@ -1509,7 +1511,13 @@
                     }
                 }
                 if (auto builtin = attributes.builtin) {
-                    auto name = builtin_to_attribute(builtin.value());
+                    std::string name;
+                    if (builtin.value() == core::BuiltinValue::kClipDistances) {
+                        name = "SV_ClipDistance" + std::to_string(which_clip_distance);
+                        ++which_clip_distance;
+                    } else {
+                        name = builtin_to_attribute(builtin.value());
+                    }
                     TINT_ASSERT(!name.empty());
 
                     post += " : " + name;
@@ -1571,7 +1579,7 @@
             default:
                 break;
         }
-        return "";
+        TINT_ICE() << "Unhandled BuiltinValue: " << ToString(builtin);
     }
 
     std::string interpolation_to_modifiers(core::InterpolationType type,
diff --git a/src/tint/lang/hlsl/writer/raise/binary_polyfill.cc b/src/tint/lang/hlsl/writer/raise/binary_polyfill.cc
index 8198a15..e3f4587 100644
--- a/src/tint/lang/hlsl/writer/raise/binary_polyfill.cc
+++ b/src/tint/lang/hlsl/writer/raise/binary_polyfill.cc
@@ -136,7 +136,10 @@
 }  // namespace
 
 Result<SuccessType> BinaryPolyfill(core::ir::Module& ir) {
-    auto result = ValidateAndDumpIfNeeded(ir, "BinaryPolyfill transform");
+    auto result = ValidateAndDumpIfNeeded(ir, "BinaryPolyfill transform",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
+                                          });
     if (result != Success) {
         return result.Failure();
     }
diff --git a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
index a8fc4b3..7504f7f 100644
--- a/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
+++ b/src/tint/lang/hlsl/writer/raise/builtin_polyfill.cc
@@ -1924,7 +1924,10 @@
 }  // namespace
 
 Result<SuccessType> BuiltinPolyfill(core::ir::Module& ir) {
-    auto result = ValidateAndDumpIfNeeded(ir, "BuiltinPolyfill transform");
+    auto result = ValidateAndDumpIfNeeded(ir, "BuiltinPolyfill transform",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
+                                          });
     if (result != Success) {
         return result.Failure();
     }
diff --git a/src/tint/lang/hlsl/writer/raise/decompose_storage_access.cc b/src/tint/lang/hlsl/writer/raise/decompose_storage_access.cc
index d1dd9f1..288bb3c 100644
--- a/src/tint/lang/hlsl/writer/raise/decompose_storage_access.cc
+++ b/src/tint/lang/hlsl/writer/raise/decompose_storage_access.cc
@@ -898,7 +898,10 @@
 }  // namespace
 
 Result<SuccessType> DecomposeStorageAccess(core::ir::Module& ir) {
-    auto result = ValidateAndDumpIfNeeded(ir, "DecomposeStorageAccess transform");
+    auto result = ValidateAndDumpIfNeeded(ir, "DecomposeStorageAccess transform",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
+                                          });
     if (result != Success) {
         return result.Failure();
     }
diff --git a/src/tint/lang/hlsl/writer/raise/decompose_uniform_access.cc b/src/tint/lang/hlsl/writer/raise/decompose_uniform_access.cc
index ca08047..dd1d9a2 100644
--- a/src/tint/lang/hlsl/writer/raise/decompose_uniform_access.cc
+++ b/src/tint/lang/hlsl/writer/raise/decompose_uniform_access.cc
@@ -586,7 +586,10 @@
 }  // namespace
 
 Result<SuccessType> DecomposeUniformAccess(core::ir::Module& ir) {
-    auto result = ValidateAndDumpIfNeeded(ir, "DecomposeUniformAccess transform");
+    auto result = ValidateAndDumpIfNeeded(ir, "DecomposeUniformAccess transform",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
+                                          });
     if (result != Success) {
         return result.Failure();
     }
diff --git a/src/tint/lang/hlsl/writer/raise/pixel_local.cc b/src/tint/lang/hlsl/writer/raise/pixel_local.cc
index 886f17f..962258f 100644
--- a/src/tint/lang/hlsl/writer/raise/pixel_local.cc
+++ b/src/tint/lang/hlsl/writer/raise/pixel_local.cc
@@ -245,7 +245,10 @@
 }  // namespace
 
 Result<SuccessType> PixelLocal(core::ir::Module& ir, const PixelLocalConfig& config) {
-    auto result = ValidateAndDumpIfNeeded(ir, "PixelLocal transform");
+    auto result = ValidateAndDumpIfNeeded(ir, "PixelLocal transform",
+                                          core::ir::Capabilities{
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
+                                          });
     if (result != Success) {
         return result.Failure();
     }
diff --git a/src/tint/lang/hlsl/writer/raise/promote_initializers.cc b/src/tint/lang/hlsl/writer/raise/promote_initializers.cc
index a996b5b..048650c 100644
--- a/src/tint/lang/hlsl/writer/raise/promote_initializers.cc
+++ b/src/tint/lang/hlsl/writer/raise/promote_initializers.cc
@@ -222,6 +222,7 @@
     auto result = ValidateAndDumpIfNeeded(ir, "PromoteInitializers transform",
                                           core::ir::Capabilities{
                                               core::ir::Capability::kAllowVectorElementPointer,
+                                              core::ir::Capability::kAllowClipDistancesOnF32,
                                           });
     if (result != Success) {
         return result;
diff --git a/src/tint/lang/hlsl/writer/raise/shader_io.cc b/src/tint/lang/hlsl/writer/raise/shader_io.cc
index dc3e420..3a68b5c 100644
--- a/src/tint/lang/hlsl/writer/raise/shader_io.cc
+++ b/src/tint/lang/hlsl/writer/raise/shader_io.cc
@@ -68,6 +68,8 @@
     std::optional<uint32_t> subgroup_invocation_id_index;
     std::optional<uint32_t> subgroup_size_index;
     std::optional<uint32_t> num_workgroups_index;
+    std::optional<uint32_t> first_clip_distance_index;
+    std::optional<uint32_t> second_clip_distance_index;
 
     /// Constructor
     StateImpl(core::ir::Module& mod, core::ir::Function* f, const ShaderIOConfig& c)
@@ -106,6 +108,8 @@
                 return 12;
             case core::BuiltinValue::kPointSize:
                 return 13;
+            case core::BuiltinValue::kClipDistances:
+                return 14;
             default:
                 break;
         }
@@ -247,6 +251,41 @@
             return ty.void_();
         }
 
+        // If a clip_distances output is found, replace it with either one or two new outputs,
+        // depending on the array size. The new outputs maintain the ClipDistance attribute, which
+        // is translated to SV_ClipDistanceN in the printer.
+        for (uint32_t i = 0; i < outputs.Length(); ++i) {
+            if (outputs[i].attributes.builtin == core::BuiltinValue::kClipDistances) {
+                auto* const type = outputs[i].type;
+                auto const name = outputs[i].name;
+                auto const attributes = outputs[i].attributes;
+                // Compute new member element counts
+                auto* arr = type->As<core::type::Array>();
+                uint32_t arr_count = *arr->ConstantCount();
+                TINT_ASSERT(arr_count >= 1 && arr_count <= 8);
+                uint32_t count0, count1;
+                if (arr_count >= 4) {
+                    count0 = 4;
+                    count1 = arr_count - 4;
+                } else {
+                    count0 = arr_count;
+                    count1 = 0;
+                }
+                // Replace current output for the first one
+                auto* ty0 = ty.MatchWidth(ty.f32(), count0);
+                auto name0 = ir.symbols.New(name.Name() + std::to_string(0));
+                outputs[i] = {name0, ty0, attributes};
+                first_clip_distance_index = i;
+                // And add a new output for the second, if any
+                if (count1 > 0) {
+                    auto* ty1 = ty.MatchWidth(ty.f32(), count1);
+                    auto name1 = ir.symbols.New(name.Name() + std::to_string(1));
+                    second_clip_distance_index = AddOutput(name1, ty1, attributes);
+                }
+                break;
+            }
+        }
+
         Vector<MemberInfo, 4> output_data;
         for (uint32_t i = 0; i < outputs.Length(); ++i) {
             output_data.Push(MemberInfo{outputs[i], i});
@@ -345,8 +384,45 @@
         return v;
     }
 
+    core::ir::Value* BuildClipDistanceInitValue(core::ir::Builder& builder,
+                                                uint32_t output_index,
+                                                core::ir::Value* src_array,
+                                                uint32_t src_array_first_index) {
+        // Copy from the array `src_array`
+        auto* src_array_ty = src_array->Type()->As<core::type::Array>();
+        TINT_ASSERT(src_array_ty);
+
+        core::ir::Value* dst_value;
+        if (auto* dst_vec_ty = outputs[output_index].type->As<core::type::Vector>()) {
+            // Create a vector and copy array elements to it
+            Vector<core::ir::Value*, 4> init;
+            for (size_t i = 0; i < dst_vec_ty->Elements().count; ++i) {
+                init.Push(
+                    builder.Access<f32>(src_array, u32(src_array_first_index + i))->Result(0));
+            }
+            dst_value = builder.Construct(dst_vec_ty, std::move(init))->Result(0);
+        } else {
+            TINT_ASSERT(outputs[output_index].type->As<core::type::Scalar>());
+            dst_value = builder.Access<f32>(src_array, u32(src_array_first_index))->Result(0);
+        }
+        return dst_value;
+    }
+
     /// @copydoc ShaderIO::BackendState::SetOutput
-    void SetOutput(core::ir::Builder&, uint32_t idx, core::ir::Value* value) override {
+    void SetOutput(core::ir::Builder& builder, uint32_t idx, core::ir::Value* value) override {
+        // If setting a ClipDistance output, build the initial value for one or both output values.
+        if (idx == first_clip_distance_index) {
+            auto index = output_indices[idx];
+            output_values[index] = BuildClipDistanceInitValue(builder, idx, value, 0);
+
+            if (second_clip_distance_index) {
+                index = output_indices[*second_clip_distance_index];
+                output_values[index] =
+                    BuildClipDistanceInitValue(builder, *second_clip_distance_index, value, 4);
+            }
+            return;
+        }
+
         auto index = output_indices[idx];
         output_values[index] = value;
     }
diff --git a/src/tint/lang/hlsl/writer/raise/shader_io_test.cc b/src/tint/lang/hlsl/writer/raise/shader_io_test.cc
index 1be886c..0691d9d 100644
--- a/src/tint/lang/hlsl/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/hlsl/writer/raise/shader_io_test.cc
@@ -1459,5 +1459,701 @@
     EXPECT_EQ(expect, str());
 }
 
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_1) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 1>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 1>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 1> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 1> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 1> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:f32 @offset(16), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 1> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 1> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:foo_outputs = construct %7, %9
+    ret %10
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_2) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 2>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 2>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 2> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 2> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 2> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec2<f32> @offset(16), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 2> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 2> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:vec2<f32> = construct %9, %10
+    %12:foo_outputs = construct %7, %11
+    ret %12
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_3) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 3>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 3>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 3> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 3> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 3> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec3<f32> @offset(16), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 3> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 3> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:f32 = access %8, 2u
+    %12:vec3<f32> = construct %9, %10, %11
+    %13:foo_outputs = construct %7, %12
+    ret %13
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_4) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 4>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 4>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 4> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 4> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 4> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec4<f32> @offset(16), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 4> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 4> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:f32 = access %8, 2u
+    %12:f32 = access %8, 3u
+    %13:vec4<f32> = construct %9, %10, %11, %12
+    %14:foo_outputs = construct %7, %13
+    ret %14
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_5) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 5>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 5>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 5> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 5> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 5> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec4<f32> @offset(16), @builtin(clip_distances)
+  Outputs_clip_distances1:f32 @offset(32), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 5> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 5> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:f32 = access %8, 2u
+    %12:f32 = access %8, 3u
+    %13:vec4<f32> = construct %9, %10, %11, %12
+    %14:f32 = access %8, 4u
+    %15:foo_outputs = construct %7, %13, %14
+    ret %15
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_6) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 6>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 6>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 6> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 6> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 6> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec4<f32> @offset(16), @builtin(clip_distances)
+  Outputs_clip_distances1:vec2<f32> @offset(32), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 6> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 6> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:f32 = access %8, 2u
+    %12:f32 = access %8, 3u
+    %13:vec4<f32> = construct %9, %10, %11, %12
+    %14:f32 = access %8, 4u
+    %15:f32 = access %8, 5u
+    %16:vec2<f32> = construct %14, %15
+    %17:foo_outputs = construct %7, %13, %16
+    ret %17
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_7) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 7>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 7>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 7> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 7> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 7> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec4<f32> @offset(16), @builtin(clip_distances)
+  Outputs_clip_distances1:vec3<f32> @offset(32), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 7> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 7> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:f32 = access %8, 2u
+    %12:f32 = access %8, 3u
+    %13:vec4<f32> = construct %9, %10, %11, %12
+    %14:f32 = access %8, 4u
+    %15:f32 = access %8, 5u
+    %16:f32 = access %8, 6u
+    %17:vec3<f32> = construct %14, %15, %16
+    %18:foo_outputs = construct %7, %13, %17
+    ret %18
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_8) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 8>(), clip_distances_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        auto* cd = b.Construct(ty.array<f32, 8>(), 0.0_f);
+        b.Return(ep, b.Construct(str_ty, pos, cd));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0), @builtin(position)
+  clip_distances:array<f32, 8> @offset(16), @builtin(clip_distances)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 8> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  position:vec4<f32> @offset(0)
+  clip_distances:array<f32, 8> @offset(16)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec4<f32> @offset(16), @builtin(clip_distances)
+  Outputs_clip_distances1:vec4<f32> @offset(32), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:vec4<f32> = construct 0.5f
+    %3:array<f32, 8> = construct 0.0f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:vec4<f32> = access %6, 0u
+    %8:array<f32, 8> = access %6, 1u
+    %9:f32 = access %8, 0u
+    %10:f32 = access %8, 1u
+    %11:f32 = access %8, 2u
+    %12:f32 = access %8, 3u
+    %13:vec4<f32> = construct %9, %10, %11, %12
+    %14:f32 = access %8, 4u
+    %15:f32 = access %8, 5u
+    %16:f32 = access %8, 6u
+    %17:f32 = access %8, 7u
+    %18:vec4<f32> = construct %14, %15, %16, %17
+    %19:foo_outputs = construct %7, %13, %18
+    ret %19
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
+TEST_F(HlslWriterTransformTest, ShaderIOParameters_ClipDistances_FirstMember) {
+    core::IOAttributes pos_attr;
+    pos_attr.builtin = core::BuiltinValue::kPosition;
+    core::IOAttributes clip_distances_attr;
+    clip_distances_attr.builtin = core::BuiltinValue::kClipDistances;
+    auto* str_ty =
+        ty.Struct(mod.symbols.New("Outputs"),
+                  {
+                      {mod.symbols.New("clip_distances"), ty.array<f32, 5>(), clip_distances_attr},
+                      {mod.symbols.New("position"), ty.vec4<f32>(), pos_attr},
+                  });
+    auto* ep = b.Function("foo", str_ty, core::ir::Function::PipelineStage::kVertex);
+    b.Append(ep->Block(), [&] {
+        auto* cd = b.Construct(ty.array<f32, 5>(), 0.0_f);
+        auto* pos = b.Construct(ty.vec4<f32>(), 0.5_f);
+        b.Return(ep, b.Construct(str_ty, cd, pos));
+    });
+
+    auto* src = R"(
+Outputs = struct @align(16) {
+  clip_distances:array<f32, 5> @offset(0), @builtin(clip_distances)
+  position:vec4<f32> @offset(32), @builtin(position)
+}
+
+%foo = @vertex func():Outputs {
+  $B1: {
+    %2:array<f32, 5> = construct 0.0f
+    %3:vec4<f32> = construct 0.5f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+)";
+    EXPECT_EQ(src, str());
+
+    auto* expect = R"(
+Outputs = struct @align(16) {
+  clip_distances:array<f32, 5> @offset(0)
+  position:vec4<f32> @offset(32)
+}
+
+foo_outputs = struct @align(16) {
+  Outputs_position:vec4<f32> @offset(0), @builtin(position)
+  Outputs_clip_distances0:vec4<f32> @offset(16), @builtin(clip_distances)
+  Outputs_clip_distances1:f32 @offset(32), @builtin(clip_distances)
+}
+
+%foo_inner = func():Outputs {
+  $B1: {
+    %2:array<f32, 5> = construct 0.0f
+    %3:vec4<f32> = construct 0.5f
+    %4:Outputs = construct %2, %3
+    ret %4
+  }
+}
+%foo = @vertex func():foo_outputs {
+  $B2: {
+    %6:Outputs = call %foo_inner
+    %7:array<f32, 5> = access %6, 0u
+    %8:f32 = access %7, 0u
+    %9:f32 = access %7, 1u
+    %10:f32 = access %7, 2u
+    %11:f32 = access %7, 3u
+    %12:vec4<f32> = construct %8, %9, %10, %11
+    %13:f32 = access %7, 4u
+    %14:vec4<f32> = access %6, 1u
+    %15:foo_outputs = construct %14, %12, %13
+    ret %15
+  }
+}
+)";
+
+    capabilities = core::ir::Capability::kAllowClipDistancesOnF32;
+    Run(ShaderIO, ShaderIOConfig{});
+
+    EXPECT_EQ(expect, str());
+}
+
 }  // namespace
 }  // namespace tint::hlsl::writer::raise
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl
deleted file mode 100644
index 3c66ae3..0000000
--- a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl
+++ /dev/null
@@ -1,11 +0,0 @@
-SKIP: FAILED
-
-..\..\src\tint\lang\hlsl\writer\raise\shader_io.cc:112 internal compiler error: TINT_UNREACHABLE Unhandled builtin value: clip_distances
-********************************************************************
-*  The tint shader compiler has encountered an unexpected error.   *
-*                                                                  *
-*  Please help us fix this issue by submitting a bug report at     *
-*  crbug.com/tint with the source program that triggered the bug.  *
-********************************************************************
-
-tint executable returned error: exit status 0xc000001d
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl
new file mode 100644
index 0000000..542395c
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 1>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 1>(0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..133dde4
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.dxc.hlsl
@@ -0,0 +1,22 @@
+struct VertexOutputs {
+  float clipDistance[1];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[1])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[1] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0 = tmp_inner_clip_distances[0u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..133dde4
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.fxc.hlsl
@@ -0,0 +1,22 @@
+struct VertexOutputs {
+  float clipDistance[1];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[1])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[1] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0 = tmp_inner_clip_distances[0u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.glsl
similarity index 100%
copy from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.glsl
copy to test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..210f726
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,25 @@
+struct VertexOutputs {
+  float clipDistance[1];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[1])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[1] = v_2.clipDistance;
+  VertexOutputs v_4 = v_1;
+  main_outputs v_5 = {v_4.position, v_3[0u]};
+  return v_5;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..210f726
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,25 @@
+struct VertexOutputs {
+  float clipDistance[1];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[1])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[1] = v_2.clipDistance;
+  VertexOutputs v_4 = v_1;
+  main_outputs v_5 = {v_4.position, v_3[0u]};
+  return v_5;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.msl
new file mode 100644
index 0000000..ddb5b47
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.ir.msl
@@ -0,0 +1,36 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 1> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [1];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 1>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.msl
new file mode 100644
index 0000000..365c088
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 1> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [1];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 1>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 1> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.spvasm
new file mode 100644
index 0000000..923ce14
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_1 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_1 = OpConstant %uint 1
+%_arr_float_uint_1 = OpTypeArray %float %uint_1
+%_ptr_Output__arr_float_uint_1 = OpTypePointer Output %_arr_float_uint_1
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_1 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_1 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_1
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_1 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.wgsl
new file mode 100644
index 0000000..542395c
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_1.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 1>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 1>(0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl
new file mode 100644
index 0000000..ba82055
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 2>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 2>(0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..34fc74c
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.dxc.hlsl
@@ -0,0 +1,23 @@
+struct VertexOutputs {
+  float clipDistance[2];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float2 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[2])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[2] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..34fc74c
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.fxc.hlsl
@@ -0,0 +1,23 @@
+struct VertexOutputs {
+  float clipDistance[2];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float2 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[2])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[2] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.glsl
new file mode 100644
index 0000000..be7db57
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+SKIP: FAILED
+
+
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 2>,
+}
+
+@vertex
+fn tint_symbol() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 2>(0.0, 0.0));
+}
+
+Failed to generate: <dawn>/test/tint/extensions/clip_distances/clip_distances_size_2.wgsl:1:8 error: GLSL backend does not support extension 'clip_distances'
+enable clip_distances;
+       ^^^^^^^^^^^^^^
+
+
+tint executable returned error: exit status 1
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..b9cfc8d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,26 @@
+struct VertexOutputs {
+  float clipDistance[2];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float2 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[2])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[2] = v_2.clipDistance;
+  float v_4[2] = v_2.clipDistance;
+  VertexOutputs v_5 = v_1;
+  main_outputs v_6 = {v_5.position, float2(v_3[0u], v_4[1u])};
+  return v_6;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..b9cfc8d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,26 @@
+struct VertexOutputs {
+  float clipDistance[2];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float2 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[2])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[2] = v_2.clipDistance;
+  float v_4[2] = v_2.clipDistance;
+  VertexOutputs v_5 = v_1;
+  main_outputs v_6 = {v_5.position, float2(v_3[0u], v_4[1u])};
+  return v_6;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.msl
new file mode 100644
index 0000000..f3ac456
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.ir.msl
@@ -0,0 +1,37 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 2> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [2];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 2>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.msl
new file mode 100644
index 0000000..66970df
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 2> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [2];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 2>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 2> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.spvasm
new file mode 100644
index 0000000..d34755c
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_2 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_2 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_2 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_2
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_2 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.wgsl
new file mode 100644
index 0000000..ba82055
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_2.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 2>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 2>(0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl
new file mode 100644
index 0000000..6a92cb5
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 3>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 3>(0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..72ea172
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.dxc.hlsl
@@ -0,0 +1,24 @@
+struct VertexOutputs {
+  float clipDistance[3];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float3 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[3])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[3] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..72ea172
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.fxc.hlsl
@@ -0,0 +1,24 @@
+struct VertexOutputs {
+  float clipDistance[3];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float3 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[3])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[3] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.glsl
similarity index 100%
copy from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.glsl
copy to test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..bcd0f54
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,27 @@
+struct VertexOutputs {
+  float clipDistance[3];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float3 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[3])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[3] = v_2.clipDistance;
+  float v_4[3] = v_2.clipDistance;
+  float v_5[3] = v_2.clipDistance;
+  VertexOutputs v_6 = v_1;
+  main_outputs v_7 = {v_6.position, float3(v_3[0u], v_4[1u], v_5[2u])};
+  return v_7;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..bcd0f54
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,27 @@
+struct VertexOutputs {
+  float clipDistance[3];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float3 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[3])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[3] = v_2.clipDistance;
+  float v_4[3] = v_2.clipDistance;
+  float v_5[3] = v_2.clipDistance;
+  VertexOutputs v_6 = v_1;
+  main_outputs v_7 = {v_6.position, float3(v_3[0u], v_4[1u], v_5[2u])};
+  return v_7;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.msl
new file mode 100644
index 0000000..49dded8
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.ir.msl
@@ -0,0 +1,38 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 3> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [3];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 3>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.msl
new file mode 100644
index 0000000..6d5fe1d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 3> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [3];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 3>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 3> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.spvasm
new file mode 100644
index 0000000..c835ca6
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_3 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_3 = OpConstant %uint 3
+%_arr_float_uint_3 = OpTypeArray %float %uint_3
+%_ptr_Output__arr_float_uint_3 = OpTypePointer Output %_arr_float_uint_3
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_3 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_3 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_3
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_3 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.wgsl
new file mode 100644
index 0000000..6a92cb5
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_3.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 3>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 3>(0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl
new file mode 100644
index 0000000..093b1ce
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 4>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 4>(0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..76c13cc
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.dxc.hlsl
@@ -0,0 +1,25 @@
+struct VertexOutputs {
+  float clipDistance[4];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[4])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[4] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..76c13cc
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.fxc.hlsl
@@ -0,0 +1,25 @@
+struct VertexOutputs {
+  float clipDistance[4];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[4])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[4] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.glsl
similarity index 100%
copy from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.glsl
copy to test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..a3ad3c5
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float clipDistance[4];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[4])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[4] = v_2.clipDistance;
+  float v_4[4] = v_2.clipDistance;
+  float v_5[4] = v_2.clipDistance;
+  float v_6[4] = v_2.clipDistance;
+  VertexOutputs v_7 = v_1;
+  main_outputs v_8 = {v_7.position, float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u])};
+  return v_8;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..a3ad3c5
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float clipDistance[4];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[4])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[4] = v_2.clipDistance;
+  float v_4[4] = v_2.clipDistance;
+  float v_5[4] = v_2.clipDistance;
+  float v_6[4] = v_2.clipDistance;
+  VertexOutputs v_7 = v_1;
+  main_outputs v_8 = {v_7.position, float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u])};
+  return v_8;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.msl
new file mode 100644
index 0000000..a931af8
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.ir.msl
@@ -0,0 +1,39 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 4> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [4];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 4>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.msl
new file mode 100644
index 0000000..6779a58
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.msl
@@ -0,0 +1,43 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 4> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [4];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 4>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 4> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.spvasm
new file mode 100644
index 0000000..923b3fe
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_4 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_4 = OpConstant %uint 4
+%_arr_float_uint_4 = OpTypeArray %float %uint_4
+%_ptr_Output__arr_float_uint_4 = OpTypePointer Output %_arr_float_uint_4
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_4 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_4 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_4
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_4 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.wgsl
new file mode 100644
index 0000000..093b1ce
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_4.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 4>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 4>(0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl
new file mode 100644
index 0000000..81b83c0
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 5>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 5>(0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..b6394c6
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.dxc.hlsl
@@ -0,0 +1,27 @@
+struct VertexOutputs {
+  float clipDistance[5];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[5])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[5] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1 = tmp_inner_clip_distances[4u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..b6394c6
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.fxc.hlsl
@@ -0,0 +1,27 @@
+struct VertexOutputs {
+  float clipDistance[5];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[5])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[5] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1 = tmp_inner_clip_distances[4u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.glsl
similarity index 100%
copy from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.glsl
copy to test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..f6b5f58
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,30 @@
+struct VertexOutputs {
+  float clipDistance[5];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[5])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[5] = v_2.clipDistance;
+  float v_4[5] = v_2.clipDistance;
+  float v_5[5] = v_2.clipDistance;
+  float v_6[5] = v_2.clipDistance;
+  float v_7[5] = v_2.clipDistance;
+  VertexOutputs v_8 = v_1;
+  main_outputs v_9 = {v_8.position, float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]), v_7[4u]};
+  return v_9;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..f6b5f58
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,30 @@
+struct VertexOutputs {
+  float clipDistance[5];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[5])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[5] = v_2.clipDistance;
+  float v_4[5] = v_2.clipDistance;
+  float v_5[5] = v_2.clipDistance;
+  float v_6[5] = v_2.clipDistance;
+  float v_7[5] = v_2.clipDistance;
+  VertexOutputs v_8 = v_1;
+  main_outputs v_9 = {v_8.position, float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]), v_7[4u]};
+  return v_9;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.msl
new file mode 100644
index 0000000..6fbb24d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.ir.msl
@@ -0,0 +1,40 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 5> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [5];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 5>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_clipDistance[4u] = v.clipDistance[4u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.msl
new file mode 100644
index 0000000..05ed844
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.msl
@@ -0,0 +1,44 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 5> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [5];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 5>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 5> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance[4u] = tmp_inner_clip_distances[4u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.spvasm
new file mode 100644
index 0000000..075b38c
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_5 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 32
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_5 = OpConstant %uint 5
+%_arr_float_uint_5 = OpTypeArray %float %uint_5
+%_ptr_Output__arr_float_uint_5 = OpTypePointer Output %_arr_float_uint_5
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_5 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_5 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_5
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_5 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.wgsl
new file mode 100644
index 0000000..81b83c0
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_5.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 5>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 5>(0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl
new file mode 100644
index 0000000..64f8b6f
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 6>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..78b20c9
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.dxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float clipDistance[6];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float2 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[6])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[6] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..78b20c9
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.fxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float clipDistance[6];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float2 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[6])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[6] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.glsl
new file mode 100644
index 0000000..55c7c68
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+SKIP: FAILED
+
+
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 6>,
+}
+
+@vertex
+fn tint_symbol() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
+
+Failed to generate: <dawn>/test/tint/extensions/clip_distances/clip_distances_size_6.wgsl:1:8 error: GLSL backend does not support extension 'clip_distances'
+enable clip_distances;
+       ^^^^^^^^^^^^^^
+
+
+tint executable returned error: exit status 1
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..767097a
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,32 @@
+struct VertexOutputs {
+  float clipDistance[6];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float2 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[6])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[6] = v_2.clipDistance;
+  float v_4[6] = v_2.clipDistance;
+  float v_5[6] = v_2.clipDistance;
+  float v_6[6] = v_2.clipDistance;
+  float4 v_7 = float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]);
+  float v_8[6] = v_2.clipDistance;
+  float v_9[6] = v_2.clipDistance;
+  VertexOutputs v_10 = v_1;
+  main_outputs v_11 = {v_10.position, v_7, float2(v_8[4u], v_9[5u])};
+  return v_11;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..767097a
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,32 @@
+struct VertexOutputs {
+  float clipDistance[6];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float2 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[6])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[6] = v_2.clipDistance;
+  float v_4[6] = v_2.clipDistance;
+  float v_5[6] = v_2.clipDistance;
+  float v_6[6] = v_2.clipDistance;
+  float4 v_7 = float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]);
+  float v_8[6] = v_2.clipDistance;
+  float v_9[6] = v_2.clipDistance;
+  VertexOutputs v_10 = v_1;
+  main_outputs v_11 = {v_10.position, v_7, float2(v_8[4u], v_9[5u])};
+  return v_11;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.msl
new file mode 100644
index 0000000..f11356d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.ir.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 6> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [6];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 6>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_clipDistance[4u] = v.clipDistance[4u];
+  tint_wrapper_result.VertexOutputs_clipDistance[5u] = v.clipDistance[5u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.msl
new file mode 100644
index 0000000..a0c8527
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.msl
@@ -0,0 +1,45 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 6> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [6];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 6>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 6> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance[4u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance[5u] = tmp_inner_clip_distances[5u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.spvasm
new file mode 100644
index 0000000..06011a8
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_6 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 32
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_6 = OpConstant %uint 6
+%_arr_float_uint_6 = OpTypeArray %float %uint_6
+%_ptr_Output__arr_float_uint_6 = OpTypePointer Output %_arr_float_uint_6
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_6 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_6 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_6
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_6 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.wgsl
new file mode 100644
index 0000000..64f8b6f
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_6.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 6>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl
new file mode 100644
index 0000000..a07aba3
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 7>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 7>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..7538126
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.dxc.hlsl
@@ -0,0 +1,29 @@
+struct VertexOutputs {
+  float clipDistance[7];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float3 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[7])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[7] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance_1[2u] = tmp_inner_clip_distances[6u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..7538126
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.fxc.hlsl
@@ -0,0 +1,29 @@
+struct VertexOutputs {
+  float clipDistance[7];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float3 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[7])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[7] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance_1[2u] = tmp_inner_clip_distances[6u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.glsl
new file mode 100644
index 0000000..26135be
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+SKIP: FAILED
+
+
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 7>,
+}
+
+@vertex
+fn tint_symbol() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 7>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
+
+Failed to generate: <dawn>/test/tint/extensions/clip_distances/clip_distances_size_7.wgsl:1:8 error: GLSL backend does not support extension 'clip_distances'
+enable clip_distances;
+       ^^^^^^^^^^^^^^
+
+
+tint executable returned error: exit status 1
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..a281078
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,33 @@
+struct VertexOutputs {
+  float clipDistance[7];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float3 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[7])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[7] = v_2.clipDistance;
+  float v_4[7] = v_2.clipDistance;
+  float v_5[7] = v_2.clipDistance;
+  float v_6[7] = v_2.clipDistance;
+  float4 v_7 = float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]);
+  float v_8[7] = v_2.clipDistance;
+  float v_9[7] = v_2.clipDistance;
+  float v_10[7] = v_2.clipDistance;
+  VertexOutputs v_11 = v_1;
+  main_outputs v_12 = {v_11.position, v_7, float3(v_8[4u], v_9[5u], v_10[6u])};
+  return v_12;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..a281078
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,33 @@
+struct VertexOutputs {
+  float clipDistance[7];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float3 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[7])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[7] = v_2.clipDistance;
+  float v_4[7] = v_2.clipDistance;
+  float v_5[7] = v_2.clipDistance;
+  float v_6[7] = v_2.clipDistance;
+  float4 v_7 = float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]);
+  float v_8[7] = v_2.clipDistance;
+  float v_9[7] = v_2.clipDistance;
+  float v_10[7] = v_2.clipDistance;
+  VertexOutputs v_11 = v_1;
+  main_outputs v_12 = {v_11.position, v_7, float3(v_8[4u], v_9[5u], v_10[6u])};
+  return v_12;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.msl
new file mode 100644
index 0000000..36182ae
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.ir.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 7> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [7];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 7>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_clipDistance[4u] = v.clipDistance[4u];
+  tint_wrapper_result.VertexOutputs_clipDistance[5u] = v.clipDistance[5u];
+  tint_wrapper_result.VertexOutputs_clipDistance[6u] = v.clipDistance[6u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.msl
new file mode 100644
index 0000000..5d87058
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.msl
@@ -0,0 +1,46 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 7> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [7];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 7>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 7> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance[4u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance[5u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance[6u] = tmp_inner_clip_distances[6u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.spvasm
new file mode 100644
index 0000000..88680e9
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_7 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 32
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_7 = OpConstant %uint 7
+%_arr_float_uint_7 = OpTypeArray %float %uint_7
+%_ptr_Output__arr_float_uint_7 = OpTypePointer Output %_arr_float_uint_7
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_7 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_7 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_7
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_7 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.wgsl
new file mode 100644
index 0000000..a07aba3
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_7.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 7>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 7>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl
new file mode 100644
index 0000000..0cbf5d0
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 8>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 8>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..3277303
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.dxc.hlsl
@@ -0,0 +1,30 @@
+struct VertexOutputs {
+  float clipDistance[8];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float4 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[8])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[8] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance_1[2u] = tmp_inner_clip_distances[6u];
+  wrapper_result.clip_distance_1[3u] = tmp_inner_clip_distances[7u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..3277303
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.fxc.hlsl
@@ -0,0 +1,30 @@
+struct VertexOutputs {
+  float clipDistance[8];
+  float4 position;
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float4 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {(float[8])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  float tmp_inner_clip_distances[8] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance_1[2u] = tmp_inner_clip_distances[6u];
+  wrapper_result.clip_distance_1[3u] = tmp_inner_clip_distances[7u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.glsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.glsl
similarity index 100%
copy from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.glsl
copy to test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..13dd80d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,34 @@
+struct VertexOutputs {
+  float clipDistance[8];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float4 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[8])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[8] = v_2.clipDistance;
+  float v_4[8] = v_2.clipDistance;
+  float v_5[8] = v_2.clipDistance;
+  float v_6[8] = v_2.clipDistance;
+  float4 v_7 = float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]);
+  float v_8[8] = v_2.clipDistance;
+  float v_9[8] = v_2.clipDistance;
+  float v_10[8] = v_2.clipDistance;
+  float v_11[8] = v_2.clipDistance;
+  VertexOutputs v_12 = v_1;
+  main_outputs v_13 = {v_12.position, v_7, float4(v_8[4u], v_9[5u], v_10[6u], v_11[7u])};
+  return v_13;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..13dd80d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,34 @@
+struct VertexOutputs {
+  float clipDistance[8];
+  float4 position;
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float4 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {(float[8])0, float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  float v_3[8] = v_2.clipDistance;
+  float v_4[8] = v_2.clipDistance;
+  float v_5[8] = v_2.clipDistance;
+  float v_6[8] = v_2.clipDistance;
+  float4 v_7 = float4(v_3[0u], v_4[1u], v_5[2u], v_6[3u]);
+  float v_8[8] = v_2.clipDistance;
+  float v_9[8] = v_2.clipDistance;
+  float v_10[8] = v_2.clipDistance;
+  float v_11[8] = v_2.clipDistance;
+  VertexOutputs v_12 = v_1;
+  main_outputs v_13 = {v_12.position, v_7, float4(v_8[4u], v_9[5u], v_10[6u], v_11[7u])};
+  return v_13;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.msl
new file mode 100644
index 0000000..442650f
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.ir.msl
@@ -0,0 +1,43 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 8> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_outputs {
+  float VertexOutputs_clipDistance [[clip_distance]] [8];
+  float4 VertexOutputs_position [[position]];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.clipDistance=tint_array<float, 8>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_clipDistance[4u] = v.clipDistance[4u];
+  tint_wrapper_result.VertexOutputs_clipDistance[5u] = v.clipDistance[5u];
+  tint_wrapper_result.VertexOutputs_clipDistance[6u] = v.clipDistance[6u];
+  tint_wrapper_result.VertexOutputs_clipDistance[7u] = v.clipDistance[7u];
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.msl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.msl
new file mode 100644
index 0000000..23e4eb5
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.msl
@@ -0,0 +1,47 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  tint_array<float, 8> clipDistance;
+  float4 position;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [8];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.clipDistance=tint_array<float, 8>{}, .position=float4(1.0f, 2.0f, 3.0f, 4.0f)};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  tint_array<float, 8> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance[4u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance[5u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance[6u] = tmp_inner_clip_distances[6u];
+  wrapper_result.clip_distance[7u] = tmp_inner_clip_distances[7u];
+  wrapper_result.position = inner_result.position;
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.spvasm
new file mode 100644
index 0000000..0baffd8
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_clip_distances_Output %main_position_Output %main___point_size_Output
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main_position_Output "main_position_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "clipDistance"
+               OpMemberName %VertexOutputs 1 "position"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %_arr_float_uint_8 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 32
+      %float = OpTypeFloat 32
+       %uint = OpTypeInt 32 0
+     %uint_8 = OpConstant %uint 8
+%_arr_float_uint_8 = OpTypeArray %float %uint_8
+%_ptr_Output__arr_float_uint_8 = OpTypePointer Output %_arr_float_uint_8
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_8 Output
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %_arr_float_uint_8 %v4float
+         %14 = OpTypeFunction %VertexOutputs
+         %17 = OpConstantNull %_arr_float_uint_8
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %18 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %16 = OpConstantComposite %VertexOutputs %17 %18
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %_arr_float_uint_8 %27 0
+               OpStore %main_clip_distances_Output %28 None
+         %29 = OpCompositeExtract %v4float %27 1
+               OpStore %main_position_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.wgsl
new file mode 100644
index 0000000..0cbf5d0
--- /dev/null
+++ b/test/tint/extensions/clip_distances/first_member/clip_distances_size_8.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(clip_distances)
+  clipDistance : array<f32, 8>,
+  @builtin(position)
+  position : vec4<f32>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(array<f32, 8>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0), vec4<f32>(1.0, 2.0, 3.0, 4.0));
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.dxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.dxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.fxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.fxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.glsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.glsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..a00b78b
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,25 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[1];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[1])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[1] = v_3.clipDistance;
+  main_outputs v_5 = {v_2.position, v_4[0u]};
+  return v_5;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..a00b78b
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,25 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[1];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[1])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[1] = v_3.clipDistance;
+  main_outputs v_5 = {v_2.position, v_4[0u]};
+  return v_5;
+}
+
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.ir.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.ir.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.spvasm
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.spvasm
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.spvasm
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_1.wgsl.expected.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_1.wgsl.expected.wgsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl
new file mode 100644
index 0000000..87d2534
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 2>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 2>(0.0, 0.0));
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..5d0e0e1
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.dxc.hlsl
@@ -0,0 +1,23 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[2];
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float2 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[2])0};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.position = inner_result.position;
+  float tmp_inner_clip_distances[2] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..5d0e0e1
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.fxc.hlsl
@@ -0,0 +1,23 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[2];
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float2 clip_distance_0 : SV_ClipDistance0;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[2])0};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.position = inner_result.position;
+  float tmp_inner_clip_distances[2] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.glsl
new file mode 100644
index 0000000..be7db57
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+SKIP: FAILED
+
+
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 2>,
+}
+
+@vertex
+fn tint_symbol() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 2>(0.0, 0.0));
+}
+
+Failed to generate: <dawn>/test/tint/extensions/clip_distances/clip_distances_size_2.wgsl:1:8 error: GLSL backend does not support extension 'clip_distances'
+enable clip_distances;
+       ^^^^^^^^^^^^^^
+
+
+tint executable returned error: exit status 1
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..a419169
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,26 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[2];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float2 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[2])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[2] = v_3.clipDistance;
+  float v_5[2] = v_3.clipDistance;
+  main_outputs v_6 = {v_2.position, float2(v_4[0u], v_5[1u])};
+  return v_6;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..a419169
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,26 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[2];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float2 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[2])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[2] = v_3.clipDistance;
+  float v_5[2] = v_3.clipDistance;
+  main_outputs v_6 = {v_2.position, float2(v_4[0u], v_5[1u])};
+  return v_6;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.msl
new file mode 100644
index 0000000..92594ed
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.ir.msl
@@ -0,0 +1,37 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  float4 position;
+  tint_array<float, 2> clipDistance;
+};
+
+struct tint_symbol_outputs {
+  float4 VertexOutputs_position [[position]];
+  float VertexOutputs_clipDistance [[clip_distance]] [2];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.position=float4(1.0f, 2.0f, 3.0f, 4.0f), .clipDistance=tint_array<float, 2>{}};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.msl
new file mode 100644
index 0000000..520401d
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  float4 position;
+  tint_array<float, 2> clipDistance;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [2];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.position=float4(1.0f, 2.0f, 3.0f, 4.0f), .clipDistance=tint_array<float, 2>{}};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  wrapper_result.position = inner_result.position;
+  tint_array<float, 2> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.spvasm
new file mode 100644
index 0000000..49f5945
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_position_Output %main_clip_distances_Output %main___point_size_Output
+               OpName %main_position_Output "main_position_Output"
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "position"
+               OpMemberName %VertexOutputs 1 "clipDistance"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %_arr_float_uint_2 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+       %uint = OpTypeInt 32 0
+     %uint_2 = OpConstant %uint 2
+%_arr_float_uint_2 = OpTypeArray %float %uint_2
+%_ptr_Output__arr_float_uint_2 = OpTypePointer Output %_arr_float_uint_2
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_2 Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %v4float %_arr_float_uint_2
+         %14 = OpTypeFunction %VertexOutputs
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %17 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %22 = OpConstantNull %_arr_float_uint_2
+         %16 = OpConstantComposite %VertexOutputs %17 %22
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %v4float %27 0
+               OpStore %main_position_Output %28 None
+         %29 = OpCompositeExtract %_arr_float_uint_2 %27 1
+               OpStore %main_clip_distances_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.wgsl
new file mode 100644
index 0000000..87d2534
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_2.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 2>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 2>(0.0, 0.0));
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.dxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.dxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.fxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.fxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.glsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.glsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..c0b0b0a
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,27 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[3];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float3 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[3])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[3] = v_3.clipDistance;
+  float v_5[3] = v_3.clipDistance;
+  float v_6[3] = v_3.clipDistance;
+  main_outputs v_7 = {v_2.position, float3(v_4[0u], v_5[1u], v_6[2u])};
+  return v_7;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..c0b0b0a
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,27 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[3];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float3 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[3])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[3] = v_3.clipDistance;
+  float v_5[3] = v_3.clipDistance;
+  float v_6[3] = v_3.clipDistance;
+  main_outputs v_7 = {v_2.position, float3(v_4[0u], v_5[1u], v_6[2u])};
+  return v_7;
+}
+
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.ir.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.ir.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.spvasm
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.spvasm
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.spvasm
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_3.wgsl.expected.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_3.wgsl.expected.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.dxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.dxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.fxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.fxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.glsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.glsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..d2953f2
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[4];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[4])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[4] = v_3.clipDistance;
+  float v_5[4] = v_3.clipDistance;
+  float v_6[4] = v_3.clipDistance;
+  float v_7[4] = v_3.clipDistance;
+  main_outputs v_8 = {v_2.position, float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u])};
+  return v_8;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..d2953f2
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[4];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[4])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[4] = v_3.clipDistance;
+  float v_5[4] = v_3.clipDistance;
+  float v_6[4] = v_3.clipDistance;
+  float v_7[4] = v_3.clipDistance;
+  main_outputs v_8 = {v_2.position, float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u])};
+  return v_8;
+}
+
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.ir.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.ir.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.spvasm
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.spvasm
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.spvasm
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_4.wgsl.expected.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_4.wgsl.expected.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.dxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.dxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.fxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.fxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.glsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.glsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..67b5ab9
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,30 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[5];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[5])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[5] = v_3.clipDistance;
+  float v_5[5] = v_3.clipDistance;
+  float v_6[5] = v_3.clipDistance;
+  float v_7[5] = v_3.clipDistance;
+  float v_8[5] = v_3.clipDistance;
+  main_outputs v_9 = {v_2.position, float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]), v_8[4u]};
+  return v_9;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..67b5ab9
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,30 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[5];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[5])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[5] = v_3.clipDistance;
+  float v_5[5] = v_3.clipDistance;
+  float v_6[5] = v_3.clipDistance;
+  float v_7[5] = v_3.clipDistance;
+  float v_8[5] = v_3.clipDistance;
+  main_outputs v_9 = {v_2.position, float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]), v_8[4u]};
+  return v_9;
+}
+
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.ir.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.ir.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.spvasm
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.spvasm
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.spvasm
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_5.wgsl.expected.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_5.wgsl.expected.wgsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl
new file mode 100644
index 0000000..c3d0c51
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 6>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..cea8817
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.dxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[6];
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float2 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[6])0};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.position = inner_result.position;
+  float tmp_inner_clip_distances[6] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..cea8817
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.fxc.hlsl
@@ -0,0 +1,28 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[6];
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float2 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[6])0};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.position = inner_result.position;
+  float tmp_inner_clip_distances[6] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.glsl
new file mode 100644
index 0000000..55c7c68
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+SKIP: FAILED
+
+
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 6>,
+}
+
+@vertex
+fn tint_symbol() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
+
+Failed to generate: <dawn>/test/tint/extensions/clip_distances/clip_distances_size_6.wgsl:1:8 error: GLSL backend does not support extension 'clip_distances'
+enable clip_distances;
+       ^^^^^^^^^^^^^^
+
+
+tint executable returned error: exit status 1
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..b6b71cd
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,32 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[6];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float2 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[6])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[6] = v_3.clipDistance;
+  float v_5[6] = v_3.clipDistance;
+  float v_6[6] = v_3.clipDistance;
+  float v_7[6] = v_3.clipDistance;
+  float4 v_8 = float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]);
+  float v_9[6] = v_3.clipDistance;
+  float v_10[6] = v_3.clipDistance;
+  main_outputs v_11 = {v_2.position, v_8, float2(v_9[4u], v_10[5u])};
+  return v_11;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..b6b71cd
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,32 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[6];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float2 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[6])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[6] = v_3.clipDistance;
+  float v_5[6] = v_3.clipDistance;
+  float v_6[6] = v_3.clipDistance;
+  float v_7[6] = v_3.clipDistance;
+  float4 v_8 = float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]);
+  float v_9[6] = v_3.clipDistance;
+  float v_10[6] = v_3.clipDistance;
+  main_outputs v_11 = {v_2.position, v_8, float2(v_9[4u], v_10[5u])};
+  return v_11;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.msl
new file mode 100644
index 0000000..5de0a0e
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.ir.msl
@@ -0,0 +1,41 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  float4 position;
+  tint_array<float, 6> clipDistance;
+};
+
+struct tint_symbol_outputs {
+  float4 VertexOutputs_position [[position]];
+  float VertexOutputs_clipDistance [[clip_distance]] [6];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.position=float4(1.0f, 2.0f, 3.0f, 4.0f), .clipDistance=tint_array<float, 6>{}};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_clipDistance[4u] = v.clipDistance[4u];
+  tint_wrapper_result.VertexOutputs_clipDistance[5u] = v.clipDistance[5u];
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.msl
new file mode 100644
index 0000000..811aefb
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.msl
@@ -0,0 +1,45 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  float4 position;
+  tint_array<float, 6> clipDistance;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [6];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.position=float4(1.0f, 2.0f, 3.0f, 4.0f), .clipDistance=tint_array<float, 6>{}};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  wrapper_result.position = inner_result.position;
+  tint_array<float, 6> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance[4u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance[5u] = tmp_inner_clip_distances[5u];
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.spvasm
new file mode 100644
index 0000000..baf336e
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_position_Output %main_clip_distances_Output %main___point_size_Output
+               OpName %main_position_Output "main_position_Output"
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "position"
+               OpMemberName %VertexOutputs 1 "clipDistance"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %_arr_float_uint_6 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+       %uint = OpTypeInt 32 0
+     %uint_6 = OpConstant %uint 6
+%_arr_float_uint_6 = OpTypeArray %float %uint_6
+%_ptr_Output__arr_float_uint_6 = OpTypePointer Output %_arr_float_uint_6
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_6 Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %v4float %_arr_float_uint_6
+         %14 = OpTypeFunction %VertexOutputs
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %17 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %22 = OpConstantNull %_arr_float_uint_6
+         %16 = OpConstantComposite %VertexOutputs %17 %22
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %v4float %27 0
+               OpStore %main_position_Output %28 None
+         %29 = OpCompositeExtract %_arr_float_uint_6 %27 1
+               OpStore %main_clip_distances_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.wgsl
new file mode 100644
index 0000000..c3d0c51
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_6.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 6>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 6>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl
new file mode 100644
index 0000000..ee16c3a
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 7>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 7>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.dxc.hlsl
new file mode 100644
index 0000000..67fa5c1
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.dxc.hlsl
@@ -0,0 +1,29 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[7];
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float3 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[7])0};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.position = inner_result.position;
+  float tmp_inner_clip_distances[7] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance_1[2u] = tmp_inner_clip_distances[6u];
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.fxc.hlsl
new file mode 100644
index 0000000..67fa5c1
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.fxc.hlsl
@@ -0,0 +1,29 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[7];
+};
+struct tint_symbol {
+  float4 position : SV_Position;
+  float4 clip_distance_0 : SV_ClipDistance0;
+  float3 clip_distance_1 : SV_ClipDistance1;
+};
+
+VertexOutputs main_inner() {
+  VertexOutputs tint_symbol_1 = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[7])0};
+  return tint_symbol_1;
+}
+
+tint_symbol main() {
+  VertexOutputs inner_result = main_inner();
+  tint_symbol wrapper_result = (tint_symbol)0;
+  wrapper_result.position = inner_result.position;
+  float tmp_inner_clip_distances[7] = inner_result.clipDistance;
+  wrapper_result.clip_distance_0[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance_0[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance_0[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance_0[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance_1[0u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance_1[1u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance_1[2u] = tmp_inner_clip_distances[6u];
+  return wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.glsl
new file mode 100644
index 0000000..26135be
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.glsl
@@ -0,0 +1,23 @@
+SKIP: FAILED
+
+
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 7>,
+}
+
+@vertex
+fn tint_symbol() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 7>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
+
+Failed to generate: <dawn>/test/tint/extensions/clip_distances/clip_distances_size_7.wgsl:1:8 error: GLSL backend does not support extension 'clip_distances'
+enable clip_distances;
+       ^^^^^^^^^^^^^^
+
+
+tint executable returned error: exit status 1
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..6c96aea
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,33 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[7];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float3 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[7])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[7] = v_3.clipDistance;
+  float v_5[7] = v_3.clipDistance;
+  float v_6[7] = v_3.clipDistance;
+  float v_7[7] = v_3.clipDistance;
+  float4 v_8 = float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]);
+  float v_9[7] = v_3.clipDistance;
+  float v_10[7] = v_3.clipDistance;
+  float v_11[7] = v_3.clipDistance;
+  main_outputs v_12 = {v_2.position, v_8, float3(v_9[4u], v_10[5u], v_11[6u])};
+  return v_12;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..6c96aea
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,33 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[7];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float3 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[7])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[7] = v_3.clipDistance;
+  float v_5[7] = v_3.clipDistance;
+  float v_6[7] = v_3.clipDistance;
+  float v_7[7] = v_3.clipDistance;
+  float4 v_8 = float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]);
+  float v_9[7] = v_3.clipDistance;
+  float v_10[7] = v_3.clipDistance;
+  float v_11[7] = v_3.clipDistance;
+  main_outputs v_12 = {v_2.position, v_8, float3(v_9[4u], v_10[5u], v_11[6u])};
+  return v_12;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.msl
new file mode 100644
index 0000000..23db246
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.ir.msl
@@ -0,0 +1,42 @@
+#include <metal_stdlib>
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+  const constant T& operator[](size_t i) const constant { return elements[i]; }
+  device T& operator[](size_t i) device { return elements[i]; }
+  const device T& operator[](size_t i) const device { return elements[i]; }
+  thread T& operator[](size_t i) thread { return elements[i]; }
+  const thread T& operator[](size_t i) const thread { return elements[i]; }
+  threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+  const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+  T elements[N];
+};
+
+struct VertexOutputs {
+  float4 position;
+  tint_array<float, 7> clipDistance;
+};
+
+struct tint_symbol_outputs {
+  float4 VertexOutputs_position [[position]];
+  float VertexOutputs_clipDistance [[clip_distance]] [7];
+};
+
+VertexOutputs tint_symbol_inner() {
+  return VertexOutputs{.position=float4(1.0f, 2.0f, 3.0f, 4.0f), .clipDistance=tint_array<float, 7>{}};
+}
+
+vertex tint_symbol_outputs tint_symbol() {
+  VertexOutputs const v = tint_symbol_inner();
+  tint_symbol_outputs tint_wrapper_result = {};
+  tint_wrapper_result.VertexOutputs_position = v.position;
+  tint_wrapper_result.VertexOutputs_clipDistance[0u] = v.clipDistance[0u];
+  tint_wrapper_result.VertexOutputs_clipDistance[1u] = v.clipDistance[1u];
+  tint_wrapper_result.VertexOutputs_clipDistance[2u] = v.clipDistance[2u];
+  tint_wrapper_result.VertexOutputs_clipDistance[3u] = v.clipDistance[3u];
+  tint_wrapper_result.VertexOutputs_clipDistance[4u] = v.clipDistance[4u];
+  tint_wrapper_result.VertexOutputs_clipDistance[5u] = v.clipDistance[5u];
+  tint_wrapper_result.VertexOutputs_clipDistance[6u] = v.clipDistance[6u];
+  return tint_wrapper_result;
+}
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.msl
new file mode 100644
index 0000000..dfb7aab
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.msl
@@ -0,0 +1,46 @@
+#include <metal_stdlib>
+
+using namespace metal;
+
+template<typename T, size_t N>
+struct tint_array {
+    const constant T& operator[](size_t i) const constant { return elements[i]; }
+    device T& operator[](size_t i) device { return elements[i]; }
+    const device T& operator[](size_t i) const device { return elements[i]; }
+    thread T& operator[](size_t i) thread { return elements[i]; }
+    const thread T& operator[](size_t i) const thread { return elements[i]; }
+    threadgroup T& operator[](size_t i) threadgroup { return elements[i]; }
+    const threadgroup T& operator[](size_t i) const threadgroup { return elements[i]; }
+    T elements[N];
+};
+
+struct VertexOutputs {
+  float4 position;
+  tint_array<float, 7> clipDistance;
+};
+
+struct tint_symbol_1 {
+  float4 position [[position]];
+  float clip_distance [[clip_distance]] [7];
+};
+
+VertexOutputs tint_symbol_inner() {
+  VertexOutputs const tint_symbol_2 = VertexOutputs{.position=float4(1.0f, 2.0f, 3.0f, 4.0f), .clipDistance=tint_array<float, 7>{}};
+  return tint_symbol_2;
+}
+
+vertex tint_symbol_1 tint_symbol() {
+  VertexOutputs const inner_result = tint_symbol_inner();
+  tint_symbol_1 wrapper_result = {};
+  wrapper_result.position = inner_result.position;
+  tint_array<float, 7> const tmp_inner_clip_distances = inner_result.clipDistance;
+  wrapper_result.clip_distance[0u] = tmp_inner_clip_distances[0u];
+  wrapper_result.clip_distance[1u] = tmp_inner_clip_distances[1u];
+  wrapper_result.clip_distance[2u] = tmp_inner_clip_distances[2u];
+  wrapper_result.clip_distance[3u] = tmp_inner_clip_distances[3u];
+  wrapper_result.clip_distance[4u] = tmp_inner_clip_distances[4u];
+  wrapper_result.clip_distance[5u] = tmp_inner_clip_distances[5u];
+  wrapper_result.clip_distance[6u] = tmp_inner_clip_distances[6u];
+  return wrapper_result;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.spvasm
new file mode 100644
index 0000000..a340d45
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.spvasm
@@ -0,0 +1,59 @@
+; SPIR-V
+; Version: 1.3
+; Generator: Google Tint Compiler; 1
+; Bound: 30
+; Schema: 0
+               OpCapability Shader
+               OpCapability ClipDistance
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Vertex %main "main" %main_position_Output %main_clip_distances_Output %main___point_size_Output
+               OpName %main_position_Output "main_position_Output"
+               OpName %main_clip_distances_Output "main_clip_distances_Output"
+               OpName %main___point_size_Output "main___point_size_Output"
+               OpName %main_inner "main_inner"
+               OpMemberName %VertexOutputs 0 "position"
+               OpMemberName %VertexOutputs 1 "clipDistance"
+               OpName %VertexOutputs "VertexOutputs"
+               OpName %main "main"
+               OpDecorate %main_position_Output BuiltIn Position
+               OpDecorate %_arr_float_uint_7 ArrayStride 4
+               OpDecorate %main_clip_distances_Output BuiltIn ClipDistance
+               OpDecorate %main___point_size_Output BuiltIn PointSize
+               OpMemberDecorate %VertexOutputs 0 Offset 0
+               OpMemberDecorate %VertexOutputs 1 Offset 16
+      %float = OpTypeFloat 32
+    %v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%main_position_Output = OpVariable %_ptr_Output_v4float Output
+       %uint = OpTypeInt 32 0
+     %uint_7 = OpConstant %uint 7
+%_arr_float_uint_7 = OpTypeArray %float %uint_7
+%_ptr_Output__arr_float_uint_7 = OpTypePointer Output %_arr_float_uint_7
+%main_clip_distances_Output = OpVariable %_ptr_Output__arr_float_uint_7 Output
+%_ptr_Output_float = OpTypePointer Output %float
+%main___point_size_Output = OpVariable %_ptr_Output_float Output
+%VertexOutputs = OpTypeStruct %v4float %_arr_float_uint_7
+         %14 = OpTypeFunction %VertexOutputs
+    %float_1 = OpConstant %float 1
+    %float_2 = OpConstant %float 2
+    %float_3 = OpConstant %float 3
+    %float_4 = OpConstant %float 4
+         %17 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
+         %22 = OpConstantNull %_arr_float_uint_7
+         %16 = OpConstantComposite %VertexOutputs %17 %22
+       %void = OpTypeVoid
+         %25 = OpTypeFunction %void
+ %main_inner = OpFunction %VertexOutputs None %14
+         %15 = OpLabel
+               OpReturnValue %16
+               OpFunctionEnd
+       %main = OpFunction %void None %25
+         %26 = OpLabel
+         %27 = OpFunctionCall %VertexOutputs %main_inner
+         %28 = OpCompositeExtract %v4float %27 0
+               OpStore %main_position_Output %28 None
+         %29 = OpCompositeExtract %_arr_float_uint_7 %27 1
+               OpStore %main_clip_distances_Output %29 None
+               OpStore %main___point_size_Output %float_1 None
+               OpReturn
+               OpFunctionEnd
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.wgsl
new file mode 100644
index 0000000..ee16c3a
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_7.wgsl.expected.wgsl
@@ -0,0 +1,13 @@
+enable clip_distances;
+
+struct VertexOutputs {
+  @builtin(position)
+  position : vec4<f32>,
+  @builtin(clip_distances)
+  clipDistance : array<f32, 7>,
+}
+
+@vertex
+fn main() -> VertexOutputs {
+  return VertexOutputs(vec4<f32>(1.0, 2.0, 3.0, 4.0), array<f32, 7>(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
+}
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.dxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.dxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.dxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.fxc.hlsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.fxc.hlsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.fxc.hlsl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.glsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.glsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.glsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.glsl
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl
new file mode 100644
index 0000000..5f2cb4e
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.dxc.hlsl
@@ -0,0 +1,34 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[8];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float4 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[8])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[8] = v_3.clipDistance;
+  float v_5[8] = v_3.clipDistance;
+  float v_6[8] = v_3.clipDistance;
+  float v_7[8] = v_3.clipDistance;
+  float4 v_8 = float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]);
+  float v_9[8] = v_3.clipDistance;
+  float v_10[8] = v_3.clipDistance;
+  float v_11[8] = v_3.clipDistance;
+  float v_12[8] = v_3.clipDistance;
+  main_outputs v_13 = {v_2.position, v_8, float4(v_9[4u], v_10[5u], v_11[6u], v_12[7u])};
+  return v_13;
+}
+
diff --git a/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl
new file mode 100644
index 0000000..5f2cb4e
--- /dev/null
+++ b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.fxc.hlsl
@@ -0,0 +1,34 @@
+struct VertexOutputs {
+  float4 position;
+  float clipDistance[8];
+};
+
+struct main_outputs {
+  float4 VertexOutputs_position : SV_Position;
+  float4 VertexOutputs_clipDistance0 : SV_ClipDistance0;
+  float4 VertexOutputs_clipDistance1 : SV_ClipDistance1;
+};
+
+
+VertexOutputs main_inner() {
+  VertexOutputs v = {float4(1.0f, 2.0f, 3.0f, 4.0f), (float[8])0};
+  return v;
+}
+
+main_outputs main() {
+  VertexOutputs v_1 = main_inner();
+  VertexOutputs v_2 = v_1;
+  VertexOutputs v_3 = v_1;
+  float v_4[8] = v_3.clipDistance;
+  float v_5[8] = v_3.clipDistance;
+  float v_6[8] = v_3.clipDistance;
+  float v_7[8] = v_3.clipDistance;
+  float4 v_8 = float4(v_4[0u], v_5[1u], v_6[2u], v_7[3u]);
+  float v_9[8] = v_3.clipDistance;
+  float v_10[8] = v_3.clipDistance;
+  float v_11[8] = v_3.clipDistance;
+  float v_12[8] = v_3.clipDistance;
+  main_outputs v_13 = {v_2.position, v_8, float4(v_9[4u], v_10[5u], v_11[6u], v_12[7u])};
+  return v_13;
+}
+
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.ir.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.ir.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.msl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.msl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.msl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.msl
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.spvasm b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.spvasm
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.spvasm
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.spvasm
diff --git a/test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.wgsl b/test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.wgsl
similarity index 100%
rename from test/tint/extensions/clip_distances/clip_distances_size_8.wgsl.expected.wgsl
rename to test/tint/extensions/clip_distances/last_member/clip_distances_size_8.wgsl.expected.wgsl
diff --git a/test/tint/parse_hlsl_errors.py b/test/tint/parse_hlsl_errors.py
index 68a4978..231b709 100644
--- a/test/tint/parse_hlsl_errors.py
+++ b/test/tint/parse_hlsl_errors.py
@@ -40,7 +40,7 @@
 parser.add_argument('--list-files', dest='list_files', action='store_true')
 parser.add_argument('--no-list-files', dest='list_files', action='store_false')
 parser.set_defaults(list_files=True)
-parser.add_argument('--ir-only', dest='ir_only', action='store_false')
+parser.add_argument('--ir-only', dest='ir_only', action='store_true')
 parser.set_defaults(ir_only=False)
 args = parser.parse_args()