Remove StructMemberOffsetAttribute.

The struct offset attribute is no longer required with the removal of
the SPIR-V AST reader.

Bug: 42250952
Change-Id: Idf8ba3cb45e4179d8ae330bee6fa0d6ddfe99a7d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/259234
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/wgsl/ast/BUILD.bazel b/src/tint/lang/wgsl/ast/BUILD.bazel
index 9236476..6f85b4d 100644
--- a/src/tint/lang/wgsl/ast/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/BUILD.bazel
@@ -102,7 +102,6 @@
     "struct.cc",
     "struct_member.cc",
     "struct_member_align_attribute.cc",
-    "struct_member_offset_attribute.cc",
     "struct_member_size_attribute.cc",
     "switch_statement.cc",
     "templated_identifier.cc",
@@ -180,7 +179,6 @@
     "struct.h",
     "struct_member.h",
     "struct_member_align_attribute.h",
-    "struct_member_offset_attribute.h",
     "struct_member_size_attribute.h",
     "switch_statement.h",
     "templated_identifier.h",
@@ -268,7 +266,6 @@
     "return_statement_test.cc",
     "stage_attribute_test.cc",
     "struct_member_align_attribute_test.cc",
-    "struct_member_offset_attribute_test.cc",
     "struct_member_size_attribute_test.cc",
     "struct_member_test.cc",
     "struct_test.cc",
diff --git a/src/tint/lang/wgsl/ast/BUILD.cmake b/src/tint/lang/wgsl/ast/BUILD.cmake
index a53fa58..d846985 100644
--- a/src/tint/lang/wgsl/ast/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/BUILD.cmake
@@ -166,8 +166,6 @@
   lang/wgsl/ast/struct_member.h
   lang/wgsl/ast/struct_member_align_attribute.cc
   lang/wgsl/ast/struct_member_align_attribute.h
-  lang/wgsl/ast/struct_member_offset_attribute.cc
-  lang/wgsl/ast/struct_member_offset_attribute.h
   lang/wgsl/ast/struct_member_size_attribute.cc
   lang/wgsl/ast/struct_member_size_attribute.h
   lang/wgsl/ast/switch_statement.cc
@@ -269,7 +267,6 @@
   lang/wgsl/ast/return_statement_test.cc
   lang/wgsl/ast/stage_attribute_test.cc
   lang/wgsl/ast/struct_member_align_attribute_test.cc
-  lang/wgsl/ast/struct_member_offset_attribute_test.cc
   lang/wgsl/ast/struct_member_size_attribute_test.cc
   lang/wgsl/ast/struct_member_test.cc
   lang/wgsl/ast/struct_test.cc
diff --git a/src/tint/lang/wgsl/ast/BUILD.gn b/src/tint/lang/wgsl/ast/BUILD.gn
index ac16190..44412f3 100644
--- a/src/tint/lang/wgsl/ast/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/BUILD.gn
@@ -172,8 +172,6 @@
     "struct_member.h",
     "struct_member_align_attribute.cc",
     "struct_member_align_attribute.h",
-    "struct_member_offset_attribute.cc",
-    "struct_member_offset_attribute.h",
     "struct_member_size_attribute.cc",
     "struct_member_size_attribute.h",
     "switch_statement.cc",
@@ -269,7 +267,6 @@
       "return_statement_test.cc",
       "stage_attribute_test.cc",
       "struct_member_align_attribute_test.cc",
-      "struct_member_offset_attribute_test.cc",
       "struct_member_size_attribute_test.cc",
       "struct_member_test.cc",
       "struct_test.cc",
diff --git a/src/tint/lang/wgsl/ast/builder.h b/src/tint/lang/wgsl/ast/builder.h
index 3dd9d66..ede2911 100644
--- a/src/tint/lang/wgsl/ast/builder.h
+++ b/src/tint/lang/wgsl/ast/builder.h
@@ -85,7 +85,6 @@
 #include "src/tint/lang/wgsl/ast/stage_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct.h"
 #include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h"
-#include "src/tint/lang/wgsl/ast/struct_member_offset_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h"
 #include "src/tint/lang/wgsl/ast/switch_statement.h"
 #include "src/tint/lang/wgsl/ast/templated_identifier.h"
@@ -2363,23 +2362,6 @@
         return MemberAccessor(source_, std::forward<OBJECT>(object), std::forward<MEMBER>(member));
     }
 
-    /// Creates a ast::StructMemberOffsetAttribute
-    /// @param val the offset expression
-    /// @returns the offset attribute pointer
-    template <typename EXPR>
-    const ast::StructMemberOffsetAttribute* MemberOffset(EXPR&& val) {
-        return create<ast::StructMemberOffsetAttribute>(source_, Expr(std::forward<EXPR>(val)));
-    }
-
-    /// Creates a ast::StructMemberOffsetAttribute
-    /// @param source the source information
-    /// @param val the offset expression
-    /// @returns the offset attribute pointer
-    template <typename EXPR>
-    const ast::StructMemberOffsetAttribute* MemberOffset(const Source& source, EXPR&& val) {
-        return create<ast::StructMemberOffsetAttribute>(source, Expr(std::forward<EXPR>(val)));
-    }
-
     /// Creates a ast::StructMemberSizeAttribute
     /// @param source the source information
     /// @param val the size value
@@ -2658,19 +2640,6 @@
                                          std::move(attributes));
     }
 
-    /// Creates a ast::StructMember with the given byte offset
-    /// @param offset the offset to use in the StructMemberOffsetAttribute
-    /// @param name the struct member name
-    /// @param type the struct member type
-    /// @returns the struct member pointer
-    template <typename NAME>
-    const ast::StructMember* Member(uint32_t offset, NAME&& name, ast::Type type) {
-        return create<ast::StructMember>(source_, Ident(std::forward<NAME>(name)), type,
-                                         Vector<const ast::Attribute*, 1>{
-                                             MemberOffset(core::AInt(offset)),
-                                         });
-    }
-
     /// Creates a ast::BlockStatement with input statements and attributes
     /// @param statements the statements of the block
     /// @param attributes the optional attributes of the block
diff --git a/src/tint/lang/wgsl/ast/struct_member_offset_attribute.cc b/src/tint/lang/wgsl/ast/struct_member_offset_attribute.cc
deleted file mode 100644
index 22da25f..0000000
--- a/src/tint/lang/wgsl/ast/struct_member_offset_attribute.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/wgsl/ast/struct_member_offset_attribute.h"
-
-#include <string>
-
-#include "src/tint/lang/wgsl/ast/builder.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::ast::StructMemberOffsetAttribute);
-
-namespace tint::ast {
-
-StructMemberOffsetAttribute::StructMemberOffsetAttribute(GenerationID pid,
-                                                         NodeID nid,
-                                                         const Source& src,
-                                                         const Expression* exp)
-    : Base(pid, nid, src), expr(exp) {}
-
-StructMemberOffsetAttribute::~StructMemberOffsetAttribute() = default;
-
-std::string StructMemberOffsetAttribute::Name() const {
-    return "offset";
-}
-
-}  // namespace tint::ast
diff --git a/src/tint/lang/wgsl/ast/struct_member_offset_attribute.h b/src/tint/lang/wgsl/ast/struct_member_offset_attribute.h
deleted file mode 100644
index bda6875..0000000
--- a/src/tint/lang/wgsl/ast/struct_member_offset_attribute.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_OFFSET_ATTRIBUTE_H_
-#define SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_OFFSET_ATTRIBUTE_H_
-
-#include <string>
-
-#include "src/tint/lang/wgsl/ast/attribute.h"
-#include "src/tint/lang/wgsl/ast/expression.h"
-
-namespace tint::ast {
-
-/// A struct member offset attribute
-/// @note The WGSL spec removed the `@offset(n)` attribute for `@size(n)`
-/// and `@align(n)` in https://github.com/gpuweb/gpuweb/pull/1447. However
-/// this attribute is kept because the SPIR-V reader has to deal with absolute
-/// offsets, and transforming these to size / align is complex and can be done
-/// in a number of ways. The Resolver is responsible for consuming the size and
-/// align attributes and transforming these into absolute offsets. It is
-/// trivial for the Resolver to handle `@offset(n)` or `@size(n)` /
-/// `@align(n)` attributes, so this is what we do, keeping all the layout
-/// logic in one place.
-class StructMemberOffsetAttribute final : public Castable<StructMemberOffsetAttribute, Attribute> {
-  public:
-    /// constructor
-    /// @param pid the identifier of the program that owns this node
-    /// @param nid the unique node identifier
-    /// @param src the source of this node
-    /// @param expr the offset expression
-    StructMemberOffsetAttribute(GenerationID pid,
-                                NodeID nid,
-                                const Source& src,
-                                const Expression* expr);
-    ~StructMemberOffsetAttribute() override;
-
-    /// @returns the WGSL name for the attribute
-    std::string Name() const override;
-
-    /// The offset expression
-    const Expression* const expr;
-};
-
-}  // namespace tint::ast
-
-#endif  // SRC_TINT_LANG_WGSL_AST_STRUCT_MEMBER_OFFSET_ATTRIBUTE_H_
diff --git a/src/tint/lang/wgsl/ast/struct_member_offset_attribute_test.cc b/src/tint/lang/wgsl/ast/struct_member_offset_attribute_test.cc
deleted file mode 100644
index 1bb65f2..0000000
--- a/src/tint/lang/wgsl/ast/struct_member_offset_attribute_test.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2020 The Dawn & Tint Authors
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this
-//    list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice,
-//    this list of conditions and the following disclaimer in the documentation
-//    and/or other materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its
-//    contributors may be used to endorse or promote products derived from
-//    this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "src/tint/lang/wgsl/ast/helper_test.h"
-
-namespace tint::ast {
-namespace {
-
-using namespace tint::core::number_suffixes;  // NOLINT
-using StructMemberOffsetAttributeTest = TestHelper;
-
-TEST_F(StructMemberOffsetAttributeTest, Creation) {
-    auto* d = MemberOffset(2_u);
-    ASSERT_TRUE(d->expr->Is<IntLiteralExpression>());
-    EXPECT_EQ(2u, d->expr->As<IntLiteralExpression>()->value);
-}
-
-}  // namespace
-}  // namespace tint::ast
diff --git a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
index 11fdb32..8255057 100644
--- a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
@@ -68,7 +68,6 @@
     kInvariant,
     kLocation,
     kMustUse,
-    kOffset,
     kSize,
     kStageCompute,
     kWorkgroupSize,
@@ -99,8 +98,6 @@
             return o << "@invariant";
         case AttributeKind::kLocation:
             return o << "@location";
-        case AttributeKind::kOffset:
-            return o << "@offset";
         case AttributeKind::kMustUse:
             return o << "@must_use";
         case AttributeKind::kSize:
@@ -184,10 +181,6 @@
                 "1:2 error: '@must_use' is not valid for " + thing,
             },
             TestParams{
-                {AttributeKind::kOffset},
-                "1:2 error: '@offset' is not valid for " + thing,
-            },
-            TestParams{
                 {AttributeKind::kSize},
                 "1:2 error: '@size' is not valid for " + thing,
             },
@@ -239,8 +232,6 @@
             return builder.Invariant(source);
         case AttributeKind::kLocation:
             return builder.Location(source, 0_a);
-        case AttributeKind::kOffset:
-            return builder.MemberOffset(source, 4_a);
         case AttributeKind::kMustUse:
             return builder.MustUse(source);
         case AttributeKind::kSize:
@@ -366,10 +357,6 @@
             R"(1:2 error: '@must_use' can only be applied to functions that return a value)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for functions)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for functions)",
         },
@@ -451,10 +438,6 @@
             Pass,
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for functions)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for functions)",
         },
@@ -542,10 +525,6 @@
             R"(1:2 error: '@must_use' is not valid for function parameters)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for function parameters)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for function parameters)",
         },
@@ -627,10 +606,6 @@
             R"(1:2 error: '@must_use' is not valid for non-entry point function return types)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for non-entry point function return types)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for non-entry point function return types)",
         },
@@ -717,10 +692,6 @@
             R"(1:2 error: '@must_use' is not valid for function parameters)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for function parameters)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for function parameters)",
         },
@@ -818,10 +789,6 @@
             R"(1:2 error: '@must_use' is not valid for function parameters)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for function parameters)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for function parameters)",
         },
@@ -925,10 +892,6 @@
             R"(1:2 error: '@must_use' is not valid for function parameters)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for function parameters)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for function parameters)",
         },
@@ -1014,10 +977,6 @@
             R"(1:2 error: '@must_use' is not valid for entry point return types)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for entry point return types)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for entry point return types)",
         },
@@ -1112,10 +1071,6 @@
             R"(1:2 error: '@must_use' is not valid for entry point return types)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for entry point return types)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for entry point return types)",
         },
@@ -1209,10 +1164,6 @@
             R"(1:2 error: '@must_use' is not valid for entry point return types)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for entry point return types)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for entry point return types)",
         },
@@ -1302,10 +1253,6 @@
             R"(1:2 error: '@must_use' is not valid for 'struct' declarations)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for 'struct' declarations)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for 'struct' declarations)",
         },
@@ -1394,10 +1341,6 @@
             R"(1:2 error: '@must_use' is not valid for 'struct' members)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            Pass,
-        },
-        TestParams{
             {AttributeKind::kSize},
             Pass,
         },
@@ -1655,10 +1598,6 @@
             R"(1:2 error: '@must_use' is not valid for 'array' types)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for 'array' types)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for 'array' types)",
         },
@@ -1738,10 +1677,6 @@
             R"(1:2 error: '@must_use' is not valid for module-scope 'var')",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for module-scope 'var')",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for module-scope 'var')",
         },
@@ -1842,10 +1777,6 @@
             R"(1:2 error: '@must_use' is not valid for 'const' declaration)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for 'const' declaration)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for 'const' declaration)",
         },
@@ -1919,10 +1850,6 @@
             R"(1:2 error: '@must_use' is not valid for 'override' declaration)",
         },
         TestParams{
-            {AttributeKind::kOffset},
-            R"(1:2 error: '@offset' is not valid for 'override' declaration)",
-        },
-        TestParams{
             {AttributeKind::kSize},
             R"(1:2 error: '@size' is not valid for 'override' declaration)",
         },
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index 6694ada..b1e6be5 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -63,7 +63,6 @@
 #include "src/tint/lang/wgsl/ast/stage_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct.h"
 #include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h"
-#include "src/tint/lang/wgsl/ast/struct_member_offset_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h"
 #include "src/tint/lang/wgsl/ast/switch_statement.h"
 #include "src/tint/lang/wgsl/ast/templated_identifier.h"
@@ -389,8 +388,7 @@
             [&](Default) {
                 if (!attr->IsAnyOf<ast::BuiltinAttribute, ast::DiagnosticAttribute,
                                    ast::InterpolateAttribute, ast::InvariantAttribute,
-                                   ast::MustUseAttribute, ast::StageAttribute,
-                                   ast::StructMemberOffsetAttribute>()) {
+                                   ast::MustUseAttribute, ast::StageAttribute>()) {
                     TINT_ICE() << "unhandled attribute type: " << attr->TypeInfo().name;
                 }
             });
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index a0cab82..a40be82 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -4273,7 +4273,6 @@
             return nullptr;
         }
 
-        bool has_offset_attr = false;
         bool has_align_attr = false;
         bool has_size_attr = false;
         core::IOAttributes attributes;
@@ -4281,32 +4280,6 @@
             Mark(attribute);
             bool ok = Switch(
                 attribute,  //
-                [&](const ast::StructMemberOffsetAttribute* attr) {
-                    // Offset attributes are not part of the WGSL spec, but are emitted by the
-                    // SPIR-V reader.
-
-                    ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant,
-                                                       "@offset value"};
-                    TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
-
-                    auto* materialized = Materialize(ValueExpression(attr->expr));
-                    if (!materialized) {
-                        return false;
-                    }
-                    auto const_value = materialized->ConstantValue();
-                    if (!const_value) {
-                        AddError(attr->expr->source) << "@offset must be constant expression";
-                        return false;
-                    }
-                    offset = const_value->ValueAs<uint64_t>();
-
-                    if (offset < struct_size) {
-                        AddError(attr->source) << "offsets must be in ascending order";
-                        return false;
-                    }
-                    has_offset_attr = true;
-                    return true;
-                },
                 [&](const ast::StructMemberAlignAttribute* attr) {
                     ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@align"};
                     TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
@@ -4428,13 +4401,6 @@
             }
         }
 
-        if (has_offset_attr && (has_align_attr || has_size_attr)) {
-            AddError(member->source)
-                << style::Attribute("@offset") << " cannot be used with "
-                << style::Attribute("@align") << " or " << style::Attribute("@size");
-            return nullptr;
-        }
-
         offset = tint::RoundUp(align, offset);
         if (offset > std::numeric_limits<uint32_t>::max()) {
             AddError(member->source)
diff --git a/src/tint/lang/wgsl/resolver/struct_layout_test.cc b/src/tint/lang/wgsl/resolver/struct_layout_test.cc
index 6602603..5235631 100644
--- a/src/tint/lang/wgsl/resolver/struct_layout_test.cc
+++ b/src/tint/lang/wgsl/resolver/struct_layout_test.cc
@@ -486,47 +486,5 @@
     }
 }
 
-TEST_F(ResolverStructLayoutTest, OffsetAttributes) {
-    auto* inner = Structure("Inner", Vector{
-                                         Member("a", ty.f32(), Vector{MemberOffset(8_i)}),
-                                         Member("b", ty.f32(), Vector{MemberOffset(16_i)}),
-                                         Member("c", ty.f32(), Vector{MemberOffset(32_i)}),
-                                     });
-    auto* s = Structure("S", Vector{
-                                 Member("a", ty.f32(), Vector{MemberOffset(4_i)}),
-                                 Member("b", ty.u32(), Vector{MemberOffset(8_i)}),
-                                 Member("c", ty.Of(inner), Vector{MemberOffset(32_i)}),
-                                 Member("d", ty.i32()),
-                                 Member("e", ty.i32(), Vector{MemberOffset(128_i)}),
-                             });
-
-    ASSERT_TRUE(r()->Resolve()) << r()->error();
-
-    auto* sem = TypeOf(s)->As<sem::Struct>();
-    ASSERT_NE(sem, nullptr);
-    EXPECT_EQ(sem->Size(), 132u);
-    EXPECT_EQ(sem->SizeNoPadding(), 132u);
-    EXPECT_EQ(sem->Align(), 4u);
-    ASSERT_EQ(sem->Members().Length(), 5u);
-    EXPECT_EQ(sem->Members()[0]->Offset(), 4u);
-    EXPECT_EQ(sem->Members()[0]->Align(), 4u);
-    EXPECT_EQ(sem->Members()[0]->Size(), 4u);
-    EXPECT_EQ(sem->Members()[1]->Offset(), 8u);
-    EXPECT_EQ(sem->Members()[1]->Align(), 4u);
-    EXPECT_EQ(sem->Members()[1]->Size(), 4u);
-    EXPECT_EQ(sem->Members()[2]->Offset(), 32u);
-    EXPECT_EQ(sem->Members()[2]->Align(), 4u);
-    EXPECT_EQ(sem->Members()[2]->Size(), 36u);
-    EXPECT_EQ(sem->Members()[3]->Offset(), 68u);
-    EXPECT_EQ(sem->Members()[3]->Align(), 4u);
-    EXPECT_EQ(sem->Members()[3]->Size(), 4u);
-    EXPECT_EQ(sem->Members()[4]->Offset(), 128u);
-    EXPECT_EQ(sem->Members()[4]->Align(), 4u);
-    EXPECT_EQ(sem->Members()[4]->Size(), 4u);
-    for (auto& m : sem->Members()) {
-        EXPECT_EQ(m->Struct()->Declaration(), s);
-    }
-}
-
 }  // namespace
 }  // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/type_validation_test.cc b/src/tint/lang/wgsl/resolver/type_validation_test.cc
index d53a538..9199534 100644
--- a/src/tint/lang/wgsl/resolver/type_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/type_validation_test.cc
@@ -357,15 +357,15 @@
 
 TEST_F(ResolverTypeValidationTest, ArraySize_TooBig_ImplicitStride) {
     // struct S {
-    //   @offset(800000) a : f32
+    //   @size(800000) a : f32
     // }
     // var<private> a : array<S, 65535>;
-    Structure("S", Vector{Member(Source{{12, 34}}, "a", ty.f32(), Vector{MemberOffset(800000_a)})});
+    Structure("S", Vector{Member(Source{{12, 34}}, "a", ty.f32(), Vector{MemberSize(800000_a)})});
     GlobalVar("a", ty.array(ty(Source{{12, 30}}, "S"), Expr(Source{{12, 34}}, 65535_a)),
               core::AddressSpace::kPrivate);
     EXPECT_FALSE(r()->Resolve());
     EXPECT_EQ(r()->error(),
-              "12:34 error: array byte size (0xc34f7cafc) must not exceed 0xffffffff bytes");
+              "12:34 error: array byte size (0xc34f3cb00) must not exceed 0xffffffff bytes");
 }
 
 TEST_F(ResolverTypeValidationTest, ArraySize_NamedOverride_PrivateVar) {
diff --git a/src/tint/lang/wgsl/resolver/validation_test.cc b/src/tint/lang/wgsl/resolver/validation_test.cc
index a9d5ba2..ce0d2e9 100644
--- a/src/tint/lang/wgsl/resolver/validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/validation_test.cc
@@ -1341,36 +1341,6 @@
               R"(12:34 error: '@size' must be at least as big as the type's size (4))");
 }
 
-TEST_F(ResolverValidationTest, OffsetAndSizeAttribute) {
-    Structure("S", Vector{
-                       Member(Source{{12, 34}}, "a", ty.f32(),
-                              Vector{MemberOffset(0_a), MemberSize(4_a)}),
-                   });
-
-    EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), R"(12:34 error: '@offset' cannot be used with '@align' or '@size')");
-}
-
-TEST_F(ResolverValidationTest, OffsetAndAlignAttribute) {
-    Structure("S", Vector{
-                       Member(Source{{12, 34}}, "a", ty.f32(),
-                              Vector{MemberOffset(0_a), MemberAlign(4_i)}),
-                   });
-
-    EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), R"(12:34 error: '@offset' cannot be used with '@align' or '@size')");
-}
-
-TEST_F(ResolverValidationTest, OffsetAndAlignAndSizeAttribute) {
-    Structure("S", Vector{
-                       Member(Source{{12, 34}}, "a", ty.f32(),
-                              Vector{MemberOffset(0_a), MemberAlign(4_i), MemberSize(4_a)}),
-                   });
-
-    EXPECT_FALSE(r()->Resolve());
-    EXPECT_EQ(r()->error(), R"(12:34 error: '@offset' cannot be used with '@align' or '@size')");
-}
-
 TEST_F(ResolverTest, Expr_Initializer_Cast_Pointer) {
     auto* vf = Var("vf", ty.f32());
     auto* c = Call(Source{{12, 34}}, ty.ptr<function, i32>(), ExprList(vf));
diff --git a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
index 876ed02..7dce971 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
@@ -69,7 +69,6 @@
 #include "src/tint/lang/wgsl/ast/return_statement.h"
 #include "src/tint/lang/wgsl/ast/stage_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h"
-#include "src/tint/lang/wgsl/ast/struct_member_offset_attribute.h"
 #include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h"
 #include "src/tint/lang/wgsl/ast/switch_statement.h"
 #include "src/tint/lang/wgsl/ast/templated_identifier.h"
@@ -405,10 +404,15 @@
         // sanitizer.
         if (auto* mem_sem = program_.Sem().Get(mem)) {
             offset = tint::RoundUp(mem_sem->Align(), offset);
+            if (mem_sem->Offset() != offset) {
+                Line() << "/* offset(" << mem_sem->Offset() << ") */";
+            }
+
             if (uint32_t padding = mem_sem->Offset() - offset) {
                 add_padding(padding);
                 offset += padding;
             }
+
             offset += mem_sem->Size();
         }
 
@@ -418,14 +422,7 @@
         Vector<const ast::Attribute*, 4> attributes_sanitized;
         attributes_sanitized.Reserve(mem->attributes.Length());
         for (auto* attr : mem->attributes) {
-            if (attr->Is<ast::StructMemberOffsetAttribute>()) {
-                auto l = Line();
-                l << "/* ";
-                EmitAttributes(l, Vector{attr});
-                l << " */";
-            } else {
-                attributes_sanitized.Push(attr);
-            }
+            attributes_sanitized.Push(attr);
         }
 
         if (!attributes_sanitized.IsEmpty()) {
@@ -554,11 +551,6 @@
                 out << ")";
             },
             [&](const ast::MustUseAttribute*) { out << "must_use"; },
-            [&](const ast::StructMemberOffsetAttribute* offset) {
-                out << "offset(";
-                EmitExpression(out, offset->expr);
-                out << ")";
-            },
             [&](const ast::StructMemberSizeAttribute* size) {
                 out << "size(";
                 EmitExpression(out, size->expr);
diff --git a/src/tint/lang/wgsl/writer/ast_printer/type_test.cc b/src/tint/lang/wgsl/writer/ast_printer/type_test.cc
index 76faee0..01f0f62 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/type_test.cc
+++ b/src/tint/lang/wgsl/writer/ast_printer/type_test.cc
@@ -184,113 +184,6 @@
     EXPECT_EQ(out.str(), "S");
 }
 
-TEST_F(WgslASTPrinterTest, EmitType_StructOffsetDecl) {
-    auto* s = Structure("S", Vector{
-                                 Member("a", ty.i32(), Vector{MemberOffset(8_a)}),
-                                 Member("b", ty.f32(), Vector{MemberOffset(16_a)}),
-                             });
-
-    ASTPrinter& gen = Build();
-
-    gen.EmitStructType(s);
-    EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.Result(), R"(struct S {
-  @size(8)
-  padding_0 : u32,
-  /* @offset(8) */
-  a : i32,
-  @size(4)
-  padding_1 : u32,
-  /* @offset(16) */
-  b : f32,
-}
-)");
-}
-
-TEST_F(WgslASTPrinterTest, EmitType_StructOffsetDecl_ExceedStaticVectorSize) {
-    auto* s = Structure("S", Vector{
-                                 Member("a", ty.i32(), Vector{MemberOffset(i32(8 * 0))}),
-                                 Member("b", ty.i32(), Vector{MemberOffset(i32(8 * 1))}),
-                                 Member("c", ty.i32(), Vector{MemberOffset(i32(8 * 2))}),
-                                 Member("d", ty.i32(), Vector{MemberOffset(i32(8 * 3))}),
-                                 Member("e", ty.i32(), Vector{MemberOffset(i32(8 * 4))}),
-                                 Member("f", ty.i32(), Vector{MemberOffset(i32(8 * 5))}),
-                                 Member("g", ty.i32(), Vector{MemberOffset(i32(8 * 6))}),
-                                 Member("h", ty.i32(), Vector{MemberOffset(i32(8 * 7))}),
-                                 Member("i", ty.i32(), Vector{MemberOffset(i32(8 * 8))}),
-                                 Member("j", ty.i32(), Vector{MemberOffset(i32(8 * 9))}),
-                             });
-
-    ASTPrinter& gen = Build();
-
-    gen.EmitStructType(s);
-    EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.Result(), R"(struct S {
-  /* @offset(0i) */
-  a : i32,
-  @size(4)
-  padding_0 : u32,
-  /* @offset(8i) */
-  b : i32,
-  @size(4)
-  padding_1 : u32,
-  /* @offset(16i) */
-  c : i32,
-  @size(4)
-  padding_2 : u32,
-  /* @offset(24i) */
-  d : i32,
-  @size(4)
-  padding_3 : u32,
-  /* @offset(32i) */
-  e : i32,
-  @size(4)
-  padding_4 : u32,
-  /* @offset(40i) */
-  f : i32,
-  @size(4)
-  padding_5 : u32,
-  /* @offset(48i) */
-  g : i32,
-  @size(4)
-  padding_6 : u32,
-  /* @offset(56i) */
-  h : i32,
-  @size(4)
-  padding_7 : u32,
-  /* @offset(64i) */
-  i : i32,
-  @size(4)
-  padding_8 : u32,
-  /* @offset(72i) */
-  j : i32,
-}
-)");
-}
-
-TEST_F(WgslASTPrinterTest, EmitType_StructOffsetDecl_WithSymbolCollisions) {
-    auto* s = Structure("S", Vector{
-                                 Member("tint_0_padding", ty.i32(), Vector{MemberOffset(8_a)}),
-                                 Member("tint_2_padding", ty.f32(), Vector{MemberOffset(16_a)}),
-                             });
-
-    ASTPrinter& gen = Build();
-
-    gen.EmitStructType(s);
-    EXPECT_THAT(gen.Diagnostics(), testing::IsEmpty());
-    EXPECT_EQ(gen.Result(), R"(struct S {
-  @size(8)
-  padding_0 : u32,
-  /* @offset(8) */
-  tint_0_padding : i32,
-  @size(4)
-  padding_1 : u32,
-  /* @offset(16) */
-  tint_2_padding : f32,
-}
-)");
-}
-
 TEST_F(WgslASTPrinterTest, EmitType_StructAlignDecl) {
     auto* s = Structure("S", Vector{
                                  Member("a", ty.i32(), Vector{MemberAlign(8_a)}),