Replace VariableDecoration::(Is|As)Location with Castable

Change-Id: I3096045fc093f3782401ce8623a18e0bca49b22c
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34309
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/binding_decoration_test.cc b/src/ast/binding_decoration_test.cc
index e3889e2..4111653 100644
--- a/src/ast/binding_decoration_test.cc
+++ b/src/ast/binding_decoration_test.cc
@@ -14,8 +14,8 @@
 
 #include "src/ast/binding_decoration.h"
 
-#include "src/ast/test_helper.h"
 #include "src/ast/constant_id_decoration.h"
+#include "src/ast/test_helper.h"
 
 namespace tint {
 namespace ast {
@@ -34,7 +34,7 @@
   EXPECT_TRUE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
-  EXPECT_FALSE(bd.IsLocation());
+  EXPECT_FALSE(d->Is<LocationDecoration>());
   EXPECT_FALSE(bd.IsSet());
 }
 
diff --git a/src/ast/builtin_decoration_test.cc b/src/ast/builtin_decoration_test.cc
index b0fa0ff..11e1b2d 100644
--- a/src/ast/builtin_decoration_test.cc
+++ b/src/ast/builtin_decoration_test.cc
@@ -34,7 +34,7 @@
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_TRUE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
-  EXPECT_FALSE(bd.IsLocation());
+  EXPECT_FALSE(d->Is<LocationDecoration>());
   EXPECT_FALSE(bd.IsSet());
 }
 
diff --git a/src/ast/constant_id_decoration_test.cc b/src/ast/constant_id_decoration_test.cc
index d784b44..ece2385 100644
--- a/src/ast/constant_id_decoration_test.cc
+++ b/src/ast/constant_id_decoration_test.cc
@@ -33,7 +33,7 @@
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_TRUE(d->Is<ConstantIdDecoration>());
-  EXPECT_FALSE(cd.IsLocation());
+  EXPECT_FALSE(d->Is<LocationDecoration>());
   EXPECT_FALSE(cd.IsSet());
 }
 
diff --git a/src/ast/decorated_variable.cc b/src/ast/decorated_variable.cc
index 2e704b1..5e5694a 100644
--- a/src/ast/decorated_variable.cc
+++ b/src/ast/decorated_variable.cc
@@ -18,6 +18,7 @@
 
 #include "src/ast/builtin_decoration.h"
 #include "src/ast/constant_id_decoration.h"
+#include "src/ast/location_decoration.h"
 
 namespace tint {
 namespace ast {
@@ -33,7 +34,7 @@
 
 bool DecoratedVariable::HasLocationDecoration() const {
   for (auto* deco : decorations_) {
-    if (deco->IsLocation()) {
+    if (deco->Is<LocationDecoration>()) {
       return true;
     }
   }
diff --git a/src/ast/function.cc b/src/ast/function.cc
index 555230b..c03694f 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -89,8 +89,8 @@
       continue;
     }
     for (auto* deco : var->AsDecorated()->decorations()) {
-      if (deco->IsLocation()) {
-        ret.push_back({var, deco->AsLocation()});
+      if (auto* location = deco->As<LocationDecoration>()) {
+        ret.push_back({var, location});
         break;
       }
     }
diff --git a/src/ast/location_decoration.cc b/src/ast/location_decoration.cc
index 3001b61..de2beae 100644
--- a/src/ast/location_decoration.cc
+++ b/src/ast/location_decoration.cc
@@ -22,10 +22,6 @@
 
 LocationDecoration::~LocationDecoration() = default;
 
-bool LocationDecoration::IsLocation() const {
-  return true;
-}
-
 void LocationDecoration::to_str(std::ostream& out, size_t indent) const {
   make_indent(out, indent);
   out << "LocationDecoration{" << value_ << "}" << std::endl;
diff --git a/src/ast/location_decoration.h b/src/ast/location_decoration.h
index e04c503..6e75d63 100644
--- a/src/ast/location_decoration.h
+++ b/src/ast/location_decoration.h
@@ -32,9 +32,6 @@
   explicit LocationDecoration(uint32_t value, const Source& source);
   ~LocationDecoration() override;
 
-  /// @returns true if this is a location decoration
-  bool IsLocation() const override;
-
   /// @returns the location value
   uint32_t value() const { return value_; }
 
diff --git a/src/ast/location_decoration_test.cc b/src/ast/location_decoration_test.cc
index 2876899..f8ffff8 100644
--- a/src/ast/location_decoration_test.cc
+++ b/src/ast/location_decoration_test.cc
@@ -36,7 +36,7 @@
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
-  EXPECT_TRUE(ld.IsLocation());
+  EXPECT_TRUE(d->Is<LocationDecoration>());
   EXPECT_FALSE(ld.IsSet());
 }
 
diff --git a/src/ast/set_decoration_test.cc b/src/ast/set_decoration_test.cc
index ceac9a7..d9b9e79 100644
--- a/src/ast/set_decoration_test.cc
+++ b/src/ast/set_decoration_test.cc
@@ -34,7 +34,7 @@
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
-  EXPECT_FALSE(sd.IsLocation());
+  EXPECT_FALSE(d->Is<LocationDecoration>());
   EXPECT_TRUE(sd.IsSet());
 }
 
diff --git a/src/ast/variable_decoration.cc b/src/ast/variable_decoration.cc
index 79e9562..287300c 100644
--- a/src/ast/variable_decoration.cc
+++ b/src/ast/variable_decoration.cc
@@ -16,7 +16,6 @@
 
 #include <assert.h>
 
-#include "src/ast/location_decoration.h"
 #include "src/ast/set_decoration.h"
 
 namespace tint {
@@ -32,19 +31,10 @@
   return Kind;
 }
 
-bool VariableDecoration::IsLocation() const {
-  return false;
-}
-
 bool VariableDecoration::IsSet() const {
   return false;
 }
 
-LocationDecoration* VariableDecoration::AsLocation() {
-  assert(IsLocation());
-  return static_cast<LocationDecoration*>(this);
-}
-
 SetDecoration* VariableDecoration::AsSet() {
   assert(IsSet());
   return static_cast<SetDecoration*>(this);
diff --git a/src/ast/variable_decoration.h b/src/ast/variable_decoration.h
index 8e6ae16..39206fb 100644
--- a/src/ast/variable_decoration.h
+++ b/src/ast/variable_decoration.h
@@ -25,8 +25,6 @@
 namespace tint {
 namespace ast {
 
-class ConstantIdDecoration;
-class LocationDecoration;
 class SetDecoration;
 
 /// A decoration attached to a variable
@@ -40,13 +38,9 @@
   /// @return the decoration kind
   DecorationKind GetKind() const override;
 
-  /// @returns true if this is a location decoration
-  virtual bool IsLocation() const;
   /// @returns true if this is a set decoration
   virtual bool IsSet() const;
 
-  /// @returns the decoration as a location decoration
-  LocationDecoration* AsLocation();
   /// @returns the decoration as a set decoration
   SetDecoration* AsSet();
 
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
index 50b5e29..3ad378c 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
@@ -36,8 +36,8 @@
   ASSERT_NE(deco_0, nullptr);
   ASSERT_NE(deco_1, nullptr);
 
-  ASSERT_TRUE(deco_0->IsLocation());
-  EXPECT_EQ(deco_0->AsLocation()->value(), 4u);
+  ASSERT_TRUE(deco_0->Is<ast::LocationDecoration>());
+  EXPECT_EQ(deco_0->As<ast::LocationDecoration>()->value(), 4u);
   ASSERT_TRUE(deco_1->Is<ast::BuiltinDecoration>());
   EXPECT_EQ(deco_1->As<ast::BuiltinDecoration>()->value(),
             ast::Builtin::kPosition);
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
index 3c9cdcb..60f1977 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
@@ -34,9 +34,9 @@
   auto* var_deco = deco.value->As<ast::VariableDecoration>();
   ASSERT_NE(var_deco, nullptr);
   ASSERT_FALSE(p->has_error());
-  ASSERT_TRUE(var_deco->IsLocation());
+  ASSERT_TRUE(var_deco->Is<ast::LocationDecoration>());
 
-  auto* loc = var_deco->AsLocation();
+  auto* loc = var_deco->As<ast::LocationDecoration>();
   EXPECT_EQ(loc->value(), 4u);
 }
 
diff --git a/src/transform/vertex_pulling_transform.cc b/src/transform/vertex_pulling_transform.cc
index 05a6ab0..11544ca 100644
--- a/src/transform/vertex_pulling_transform.cc
+++ b/src/transform/vertex_pulling_transform.cc
@@ -200,18 +200,16 @@
     }
 
     for (auto* d : v->AsDecorated()->decorations()) {
-      if (!d->IsLocation()) {
-        continue;
+      if (auto* l = d->As<ast::LocationDecoration>()) {
+        uint32_t location = l->value();
+        // This is where the replacement happens. Expressions use identifier
+        // strings instead of pointers, so we don't need to update any other
+        // place in the AST.
+        v = create<ast::Variable>(v->name(), ast::StorageClass::kPrivate,
+                                  v->type());
+        location_to_var_[location] = v;
+        break;
       }
-
-      uint32_t location = d->AsLocation()->value();
-      // This is where the replacement happens. Expressions use identifier
-      // strings instead of pointers, so we don't need to update any other place
-      // in the AST.
-      v = create<ast::Variable>(v->name(), ast::StorageClass::kPrivate,
-                                v->type());
-      location_to_var_[location] = v;
-      break;
     }
   }
 }
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index a8d14d4..38a974f 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -1377,15 +1377,14 @@
       }
 
       out << " " << var->name() << " : ";
-      if (deco->IsLocation()) {
+      if (auto* location = deco->As<ast::LocationDecoration>()) {
         if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
           error_ = "invalid location variable for pipeline stage";
           return false;
         }
-        out << "TEXCOORD" << deco->AsLocation()->value();
-      } else if (deco->Is<ast::BuiltinDecoration>()) {
-        auto attr =
-            builtin_to_attribute(deco->As<ast::BuiltinDecoration>()->value());
+        out << "TEXCOORD" << location->value();
+      } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
+        auto attr = builtin_to_attribute(builtin->value());
         if (attr.empty()) {
           error_ = "unsupported builtin";
           return false;
@@ -1424,8 +1423,8 @@
 
       out << " " << var->name() << " : ";
 
-      if (deco->IsLocation()) {
-        auto loc = deco->AsLocation()->value();
+      if (auto* location = deco->As<ast::LocationDecoration>()) {
+        auto loc = location->value();
         if (func->pipeline_stage() == ast::PipelineStage::kVertex) {
           out << "TEXCOORD" << loc;
         } else if (func->pipeline_stage() == ast::PipelineStage::kFragment) {
@@ -1434,9 +1433,8 @@
           error_ = "invalid location variable for pipeline stage";
           return false;
         }
-      } else if (deco->Is<ast::BuiltinDecoration>()) {
-        auto attr =
-            builtin_to_attribute(deco->As<ast::BuiltinDecoration>()->value());
+      } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
+        auto attr = builtin_to_attribute(builtin->value());
         if (attr.empty()) {
           error_ = "unsupported builtin";
           return false;
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index d38c9d9..d7d2fb2 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -1060,8 +1060,8 @@
 
       out_ << " " << var->name() << " [[";
 
-      if (deco->IsLocation()) {
-        auto loc = deco->AsLocation()->value();
+      if (auto* location = deco->As<ast::LocationDecoration>()) {
+        auto loc = location->value();
         if (func->pipeline_stage() == ast::PipelineStage::kVertex) {
           out_ << "user(locn" << loc << ")";
         } else if (func->pipeline_stage() == ast::PipelineStage::kFragment) {
@@ -1070,9 +1070,8 @@
           error_ = "invalid location variable for pipeline stage";
           return false;
         }
-      } else if (deco->Is<ast::BuiltinDecoration>()) {
-        auto attr =
-            builtin_to_attribute(deco->As<ast::BuiltinDecoration>()->value());
+      } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
+        auto attr = builtin_to_attribute(builtin->value());
         if (attr.empty()) {
           error_ = "unsupported builtin";
           return false;
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 43b0507..5b800a4 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -784,10 +784,10 @@
         push_annot(spv::Op::OpDecorate,
                    {Operand::Int(var_id), Operand::Int(SpvDecorationBuiltIn),
                     Operand::Int(ConvertBuiltin(builtin->value()))});
-      } else if (deco->IsLocation()) {
+      } else if (auto* location = deco->As<ast::LocationDecoration>()) {
         push_annot(spv::Op::OpDecorate,
                    {Operand::Int(var_id), Operand::Int(SpvDecorationLocation),
-                    Operand::Int(deco->AsLocation()->value())});
+                    Operand::Int(location->value())});
       } else if (auto* binding = deco->As<ast::BindingDecoration>()) {
         push_annot(spv::Op::OpDecorate,
                    {Operand::Int(var_id), Operand::Int(SpvDecorationBinding),
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index b22a529..95a227f 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -645,8 +645,8 @@
       out_ << "binding(" << binding->value() << ")";
     } else if (deco->IsSet()) {
       out_ << "set(" << deco->AsSet()->value() << ")";
-    } else if (deco->IsLocation()) {
-      out_ << "location(" << deco->AsLocation()->value() << ")";
+    } else if (auto* location = deco->As<ast::LocationDecoration>()) {
+      out_ << "location(" << location->value() << ")";
     } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
       out_ << "builtin(" << builtin->value() << ")";
     } else if (auto* cid = deco->As<ast::ConstantIdDecoration>()) {