Add ast::DisableValidationDecoration

An [[internal]] decoration that specifically disables certain validation checks.
Begin with a single kFunctionHasNoBody mode.
Migrate the Resolver to using this instead of allowing any InternalDecoration to disable the checks for no-body.

Bug: tint:797
Change-Id: I213b9a6844a456775ede06d60e456d9f77a449d0
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/50741
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 8095bea..cede2c5 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -26,6 +26,7 @@
 #include "src/ast/call_statement.h"
 #include "src/ast/continue_statement.h"
 #include "src/ast/depth_texture.h"
+#include "src/ast/disable_validation_decoration.h"
 #include "src/ast/discard_statement.h"
 #include "src/ast/fallthrough_statement.h"
 #include "src/ast/if_statement.h"
@@ -121,6 +122,21 @@
   }
 }
 
+/// @returns true if the decoration list contains a
+/// ast::DisableValidationDecoration with the validation mode equal to
+/// `validation`
+bool IsValidationDisabled(const ast::DecorationList& decorations,
+                          ast::DisabledValidation validation) {
+  for (auto* decoration : decorations) {
+    if (auto* dv = decoration->As<ast::DisableValidationDecoration>()) {
+      if (dv->Validation() == validation) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 }  // namespace
 
 Resolver::Resolver(ProgramBuilder* builder)
@@ -749,11 +765,12 @@
             func->source());
         return false;
       }
-    } else if (!ast::HasDecoration<ast::InternalDecoration>(
-                   func->decorations())) {
+    } else if (!IsValidationDisabled(
+                   func->decorations(),
+                   ast::DisabledValidation::kFunctionHasNoBody)) {
       TINT_ICE(diagnostics_)
           << "Function " << builder_->Symbols().NameFor(func->symbol())
-          << " has no body and does not have the [[internal]] decoration";
+          << " has no body";
     }
 
     for (auto* deco : func->return_type_decorations()) {