[ir][validator] Fix return value check for void functions.

If a function returns `void` the `CheckReturn` in the IR validator was
just checking if the return `Value` was true. In the case where the
return has a value of `undef` then that check would not trigger as
`nullptr` is false.

Add a `HasValue` into the `ir::Return` so we can determine if anything
exists in the operands, instead of checking the truthyness of the value
itself.

Bug: 422810448
Change-Id: I9d0c72632144289fd05c2aecef82972ade757066
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/246154
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/return.h b/src/tint/lang/core/ir/return.h
index 6ebff1c..574dccf 100644
--- a/src/tint/lang/core/ir/return.h
+++ b/src/tint/lang/core/ir/return.h
@@ -81,10 +81,11 @@
     /// @returns the function being returned
     const Function* Func() const;
 
+    /// @returns true if the return has a value set
+    bool HasValue() const { return operands_.Length() > kArgsOperandOffset; }
+
     /// @returns the return value, or nullptr
-    ir::Value* Value() const {
-        return operands_.Length() > kArgsOperandOffset ? operands_[kArgsOperandOffset] : nullptr;
-    }
+    ir::Value* Value() const { return HasValue() ? operands_[kArgsOperandOffset] : nullptr; }
 
     /// Sets the return value
     /// @param val the new return value
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index b6998df..2b49e18 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -3626,7 +3626,7 @@
     }
 
     if (func->ReturnType()->Is<core::type::Void>()) {
-        if (ret->Value()) {
+        if (ret->HasValue()) {
             AddError(ret) << "unexpected return value";
         }
     } else {
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 125686b..8ab90e5 100644
--- a/src/tint/lang/core/ir/validator_flow_control_test.cc
+++ b/src/tint/lang/core/ir/validator_flow_control_test.cc
@@ -1868,6 +1868,21 @@
 )")) << res.Failure();
 }
 
+TEST_F(IR_ValidatorTest, Return_UnexpectedValue_NullValue_WithVoid) {
+    auto* f = b.Function("my_func", ty.void_());
+    b.Append(f->Block(), [&] {  //
+        b.Return(f, nullptr);
+    });
+
+    auto res = ir::Validate(mod);
+    ASSERT_NE(res, Success);
+    EXPECT_THAT(res.Failure().reason,
+                testing::HasSubstr(R"(:3:5 error: return: unexpected return value
+    ret undef
+    ^^^^^^^^^
+)")) << res.Failure();
+}
+
 TEST_F(IR_ValidatorTest, Return_MissingValue) {
     auto* f = b.Function("my_func", ty.i32());
     b.Append(f->Block(), [&] {  //