Validate number of operands for if and switch.

Instead of validating the specific operand for the `if` and `switch`
instructions validate that there is only 1 instruction that it is valid.
Fixes an issue where we can accidentally set multiple operands into an
`if` where the operand is actually invalid.

Fixed: 442245491
Change-Id: Ib8d9a5dd35535e55bbe76f4a55737721b59c3805
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/261215
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/if.h b/src/tint/lang/core/ir/if.h
index 993bc48..9b7aabe 100644
--- a/src/tint/lang/core/ir/if.h
+++ b/src/tint/lang/core/ir/if.h
@@ -58,6 +58,8 @@
 /// ```
 class If : public Castable<If, ControlInstruction> {
   public:
+    /// The number of supported operands
+    static constexpr size_t kNumOperands = 1;
     /// The index of the condition operand
     static constexpr size_t kConditionOperandOffset = 0;
 
diff --git a/src/tint/lang/core/ir/switch.h b/src/tint/lang/core/ir/switch.h
index 199e028..b6c44d9 100644
--- a/src/tint/lang/core/ir/switch.h
+++ b/src/tint/lang/core/ir/switch.h
@@ -60,6 +60,8 @@
 /// ```
 class Switch final : public Castable<Switch, ControlInstruction> {
   public:
+    /// The number of supported operands
+    static constexpr size_t kNumOperands = 1;
     /// The offset in Operands() for the condition
     static constexpr size_t kConditionOperandOffset = 0;
 
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 334daea..82af55e 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -3546,7 +3546,7 @@
 
 void Validator::CheckIf(const If* if_) {
     CheckResults(if_);
-    CheckOperand(if_, If::kConditionOperandOffset);
+    CheckOperands(if_, If::kNumOperands);
 
     if (if_->Condition() && !if_->Condition()->Type()->Is<core::type::Bool>()) {
         AddError(if_, If::kConditionOperandOffset) << "condition type must be 'bool'";
@@ -3655,7 +3655,7 @@
 
 void Validator::CheckSwitch(const Switch* s) {
     CheckResults(s);
-    CheckOperand(s, Switch::kConditionOperandOffset);
+    CheckOperands(s, Switch::kNumOperands);
 
     if (s->Condition() && !s->Condition()->Type()->IsIntegerScalar()) {
         auto* cond_ty = s->Condition() ? s->Condition()->Type() : nullptr;
diff --git a/src/tint/lang/core/ir/validator_flow_control_test.cc b/src/tint/lang/core/ir/validator_flow_control_test.cc
index 4c89e1a..74823fd 100644
--- a/src/tint/lang/core/ir/validator_flow_control_test.cc
+++ b/src/tint/lang/core/ir/validator_flow_control_test.cc
@@ -2189,7 +2189,8 @@
 
     auto res = ir::Validate(mod);
     ASSERT_NE(res, Success);
-    EXPECT_THAT(res.Failure().reason, testing::HasSubstr(R"(error: switch: operand is undefined
+    EXPECT_THAT(res.Failure().reason,
+                testing::HasSubstr(R"(error: switch: expected exactly 1 operands, got 0
 )")) << res.Failure();
 }