spirv-diff: Fix OpTypeFunction matching w.r.t operand count (#4771)

The code accidentally expected OpTypeFunction operand count to match.
This is fixed so that OpTypeFunction instructions with different operand
counts are considered not matching.
diff --git a/source/diff/diff.cpp b/source/diff/diff.cpp
index 4ddbbd3..bca31b0 100644
--- a/source/diff/diff.cpp
+++ b/source/diff/diff.cpp
@@ -2196,16 +2196,18 @@
         case SpvOpTypeSampledImage:
         case SpvOpTypeRuntimeArray:
         case SpvOpTypePointer:
-        case SpvOpTypeFunction:
           // Match these instructions when all operands match.
           assert(src_inst->NumInOperandWords() ==
                  dst_inst->NumInOperandWords());
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
 
+        case SpvOpTypeFunction:
         case SpvOpTypeImage:
-          // Match these instructions when all operands match, including the
-          // optional final parameter (if provided in both).
+          // Match function types only if they have the same number of operands,
+          // and they all match.
+          // Match image types similarly, expecting the optional final parameter
+          // to match (if provided in both)
           if (src_inst->NumInOperandWords() != dst_inst->NumInOperandWords()) {
             return false;
           }
diff --git a/test/diff/diff_files/diff_test_files_autogen.cmake b/test/diff/diff_files/diff_test_files_autogen.cmake
index c64eaab..e6d3645 100644
--- a/test/diff/diff_files/diff_test_files_autogen.cmake
+++ b/test/diff/diff_files/diff_test_files_autogen.cmake
@@ -28,6 +28,7 @@
 "diff_files/constant_array_size_autogen.cpp"
 "diff_files/different_decorations_fragment_autogen.cpp"
 "diff_files/different_decorations_vertex_autogen.cpp"
+"diff_files/different_function_parameter_count_autogen.cpp"
 "diff_files/extra_if_block_autogen.cpp"
 "diff_files/index_signedness_autogen.cpp"
 "diff_files/int_vs_uint_constants_autogen.cpp"
diff --git a/test/diff/diff_files/different_function_parameter_count_autogen.cpp b/test/diff/diff_files/different_function_parameter_count_autogen.cpp
new file mode 100644
index 0000000..3a077fb
--- /dev/null
+++ b/test/diff/diff_files/different_function_parameter_count_autogen.cpp
@@ -0,0 +1,339 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_tests.py
+//
+// Copyright (c) 2022 Google LLC.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "../diff_test_utils.h"
+
+#include "gtest/gtest.h"
+
+namespace spvtools {
+namespace diff {
+namespace {
+
+// Test where src and dst have a function with different parameter count.
+constexpr char kSrc[] = R"(; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 10
+; Bound: 25
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %20
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpName %4 "main"
+               OpName %11 "f(vf2;"
+               OpName %10 "v"
+               OpName %20 "o"
+               OpName %23 "param"
+               OpDecorate %20 RelaxedPrecision
+               OpDecorate %20 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+          %9 = OpTypeFunction %7 %8
+         %14 = OpConstant %6 0.5
+         %15 = OpConstantComposite %7 %14 %14
+         %19 = OpTypePointer Output %7
+         %20 = OpVariable %19 Output
+         %21 = OpConstant %6 0
+         %22 = OpConstantComposite %7 %21 %21
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %23 = OpVariable %8 Function
+               OpStore %23 %22
+         %24 = OpFunctionCall %7 %11 %23
+               OpStore %20 %24
+               OpReturn
+               OpFunctionEnd
+         %11 = OpFunction %7 None %9
+         %10 = OpFunctionParameter %8
+         %12 = OpLabel
+         %13 = OpLoad %7 %10
+         %16 = OpFAdd %7 %13 %15
+               OpReturnValue %16
+               OpFunctionEnd)";
+constexpr char kDst[] = R"(; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 10
+; Bound: 28
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %20
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpName %4 "main"
+               OpName %12 "f(vf2;vf2;"
+               OpName %10 "v"
+               OpName %11 "v2"
+               OpName %20 "o"
+               OpName %25 "param"
+               OpName %26 "param"
+               OpDecorate %20 RelaxedPrecision
+               OpDecorate %20 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+          %9 = OpTypeFunction %7 %8 %8
+         %19 = OpTypePointer Output %7
+         %20 = OpVariable %19 Output
+         %21 = OpConstant %6 0
+         %22 = OpConstantComposite %7 %21 %21
+         %23 = OpConstant %6 0.5
+         %24 = OpConstantComposite %7 %23 %23
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %25 = OpVariable %8 Function
+         %26 = OpVariable %8 Function
+               OpStore %25 %22
+               OpStore %26 %24
+         %27 = OpFunctionCall %7 %12 %25 %26
+               OpStore %20 %27
+               OpReturn
+               OpFunctionEnd
+         %12 = OpFunction %7 None %9
+         %10 = OpFunctionParameter %8
+         %11 = OpFunctionParameter %8
+         %13 = OpLabel
+         %14 = OpLoad %7 %10
+         %15 = OpLoad %7 %11
+         %16 = OpFAdd %7 %14 %15
+               OpReturnValue %16
+               OpFunctionEnd
+
+)";
+
+TEST(DiffTest, DifferentFunctionParameterCount) {
+  constexpr char kDiff[] = R"( ; SPIR-V
+ ; Version: 1.6
+ ; Generator: Khronos SPIR-V Tools Assembler; 0
+-; Bound: 25
++; Bound: 33
+ ; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main" %20
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ OpName %4 "main"
+-OpName %11 "f(vf2;"
++OpName %11 "f(vf2;vf2;"
+ OpName %10 "v"
++OpName %26 "v2"
+ OpName %20 "o"
+ OpName %23 "param"
++OpName %31 "param"
+ OpDecorate %20 RelaxedPrecision
+ OpDecorate %20 Location 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeVector %6 2
+ %8 = OpTypePointer Function %7
+-%9 = OpTypeFunction %7 %8
++%25 = OpTypeFunction %7 %8 %8
+ %14 = OpConstant %6 0.5
+ %15 = OpConstantComposite %7 %14 %14
+ %19 = OpTypePointer Output %7
+ %20 = OpVariable %19 Output
+ %21 = OpConstant %6 0
+ %22 = OpConstantComposite %7 %21 %21
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %23 = OpVariable %8 Function
++%31 = OpVariable %8 Function
+ OpStore %23 %22
+-%24 = OpFunctionCall %7 %11 %23
++OpStore %31 %15
++%32 = OpFunctionCall %7 %11 %23 %31
+-OpStore %20 %24
++OpStore %20 %32
+ OpReturn
+ OpFunctionEnd
+-%11 = OpFunction %7 None %9
++%11 = OpFunction %7 None %25
+ %10 = OpFunctionParameter %8
++%26 = OpFunctionParameter %8
+ %12 = OpLabel
+ %13 = OpLoad %7 %10
+-%16 = OpFAdd %7 %13 %15
++%27 = OpLoad %7 %26
++%28 = OpFAdd %7 %13 %27
+-OpReturnValue %16
++OpReturnValue %28
+ OpFunctionEnd
+)";
+  Options options;
+  DoStringDiffTest(kSrc, kDst, kDiff, options);
+}
+
+TEST(DiffTest, DifferentFunctionParameterCountNoDebug) {
+  constexpr char kSrcNoDebug[] = R"(; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 10
+; Bound: 25
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %20
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpDecorate %20 RelaxedPrecision
+               OpDecorate %20 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+          %9 = OpTypeFunction %7 %8
+         %14 = OpConstant %6 0.5
+         %15 = OpConstantComposite %7 %14 %14
+         %19 = OpTypePointer Output %7
+         %20 = OpVariable %19 Output
+         %21 = OpConstant %6 0
+         %22 = OpConstantComposite %7 %21 %21
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %23 = OpVariable %8 Function
+               OpStore %23 %22
+         %24 = OpFunctionCall %7 %11 %23
+               OpStore %20 %24
+               OpReturn
+               OpFunctionEnd
+         %11 = OpFunction %7 None %9
+         %10 = OpFunctionParameter %8
+         %12 = OpLabel
+         %13 = OpLoad %7 %10
+         %16 = OpFAdd %7 %13 %15
+               OpReturnValue %16
+               OpFunctionEnd
+)";
+  constexpr char kDstNoDebug[] = R"(; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 10
+; Bound: 28
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %20
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpDecorate %20 RelaxedPrecision
+               OpDecorate %20 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+          %9 = OpTypeFunction %7 %8 %8
+         %19 = OpTypePointer Output %7
+         %20 = OpVariable %19 Output
+         %21 = OpConstant %6 0
+         %22 = OpConstantComposite %7 %21 %21
+         %23 = OpConstant %6 0.5
+         %24 = OpConstantComposite %7 %23 %23
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %25 = OpVariable %8 Function
+         %26 = OpVariable %8 Function
+               OpStore %25 %22
+               OpStore %26 %24
+         %27 = OpFunctionCall %7 %12 %25 %26
+               OpStore %20 %27
+               OpReturn
+               OpFunctionEnd
+         %12 = OpFunction %7 None %9
+         %10 = OpFunctionParameter %8
+         %11 = OpFunctionParameter %8
+         %13 = OpLabel
+         %14 = OpLoad %7 %10
+         %15 = OpLoad %7 %11
+         %16 = OpFAdd %7 %14 %15
+               OpReturnValue %16
+               OpFunctionEnd
+
+)";
+  constexpr char kDiff[] = R"( ; SPIR-V
+ ; Version: 1.6
+ ; Generator: Khronos SPIR-V Tools Assembler; 0
+-; Bound: 25
++; Bound: 34
+ ; Schema: 0
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main" %20
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ OpDecorate %20 RelaxedPrecision
+ OpDecorate %20 Location 0
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeFloat 32
+ %7 = OpTypeVector %6 2
+ %8 = OpTypePointer Function %7
+-%9 = OpTypeFunction %7 %8
++%25 = OpTypeFunction %7 %8 %8
+ %14 = OpConstant %6 0.5
+ %15 = OpConstantComposite %7 %14 %14
+ %19 = OpTypePointer Output %7
+ %20 = OpVariable %19 Output
+ %21 = OpConstant %6 0
+ %22 = OpConstantComposite %7 %21 %21
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %23 = OpVariable %8 Function
++%32 = OpVariable %8 Function
+ OpStore %23 %22
+-%24 = OpFunctionCall %7 %11 %23
++OpStore %32 %15
++%33 = OpFunctionCall %7 %11 %23 %32
+-OpStore %20 %24
++OpStore %20 %33
+ OpReturn
+ OpFunctionEnd
+-%11 = OpFunction %7 None %9
++%11 = OpFunction %7 None %25
+-%10 = OpFunctionParameter %8
++%26 = OpFunctionParameter %8
++%27 = OpFunctionParameter %8
+ %12 = OpLabel
+-%13 = OpLoad %7 %10
++%13 = OpLoad %7 %26
+-%16 = OpFAdd %7 %13 %15
++%28 = OpLoad %7 %27
++%29 = OpFAdd %7 %13 %28
+-OpReturnValue %16
++OpReturnValue %29
+ OpFunctionEnd
+)";
+  Options options;
+  DoStringDiffTest(kSrcNoDebug, kDstNoDebug, kDiff, options);
+}
+
+}  // namespace
+}  // namespace diff
+}  // namespace spvtools
diff --git a/test/diff/diff_files/different_function_parameter_count_dst.spvasm b/test/diff/diff_files/different_function_parameter_count_dst.spvasm
new file mode 100644
index 0000000..9244260
--- /dev/null
+++ b/test/diff/diff_files/different_function_parameter_count_dst.spvasm
@@ -0,0 +1,52 @@
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 10
+; Bound: 28
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %20
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpName %4 "main"
+               OpName %12 "f(vf2;vf2;"
+               OpName %10 "v"
+               OpName %11 "v2"
+               OpName %20 "o"
+               OpName %25 "param"
+               OpName %26 "param"
+               OpDecorate %20 RelaxedPrecision
+               OpDecorate %20 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+          %9 = OpTypeFunction %7 %8 %8
+         %19 = OpTypePointer Output %7
+         %20 = OpVariable %19 Output
+         %21 = OpConstant %6 0
+         %22 = OpConstantComposite %7 %21 %21
+         %23 = OpConstant %6 0.5
+         %24 = OpConstantComposite %7 %23 %23
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %25 = OpVariable %8 Function
+         %26 = OpVariable %8 Function
+               OpStore %25 %22
+               OpStore %26 %24
+         %27 = OpFunctionCall %7 %12 %25 %26
+               OpStore %20 %27
+               OpReturn
+               OpFunctionEnd
+         %12 = OpFunction %7 None %9
+         %10 = OpFunctionParameter %8
+         %11 = OpFunctionParameter %8
+         %13 = OpLabel
+         %14 = OpLoad %7 %10
+         %15 = OpLoad %7 %11
+         %16 = OpFAdd %7 %14 %15
+               OpReturnValue %16
+               OpFunctionEnd
+
diff --git a/test/diff/diff_files/different_function_parameter_count_src.spvasm b/test/diff/diff_files/different_function_parameter_count_src.spvasm
new file mode 100644
index 0000000..6ee2408
--- /dev/null
+++ b/test/diff/diff_files/different_function_parameter_count_src.spvasm
@@ -0,0 +1,46 @@
+;; Test where src and dst have a function with different parameter count.
+; SPIR-V
+; Version: 1.0
+; Generator: Khronos Glslang Reference Front End; 10
+; Bound: 25
+; Schema: 0
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %4 "main" %20
+               OpExecutionMode %4 OriginUpperLeft
+               OpSource ESSL 320
+               OpName %4 "main"
+               OpName %11 "f(vf2;"
+               OpName %10 "v"
+               OpName %20 "o"
+               OpName %23 "param"
+               OpDecorate %20 RelaxedPrecision
+               OpDecorate %20 Location 0
+          %2 = OpTypeVoid
+          %3 = OpTypeFunction %2
+          %6 = OpTypeFloat 32
+          %7 = OpTypeVector %6 2
+          %8 = OpTypePointer Function %7
+          %9 = OpTypeFunction %7 %8
+         %14 = OpConstant %6 0.5
+         %15 = OpConstantComposite %7 %14 %14
+         %19 = OpTypePointer Output %7
+         %20 = OpVariable %19 Output
+         %21 = OpConstant %6 0
+         %22 = OpConstantComposite %7 %21 %21
+          %4 = OpFunction %2 None %3
+          %5 = OpLabel
+         %23 = OpVariable %8 Function
+               OpStore %23 %22
+         %24 = OpFunctionCall %7 %11 %23
+               OpStore %20 %24
+               OpReturn
+               OpFunctionEnd
+         %11 = OpFunction %7 None %9
+         %10 = OpFunctionParameter %8
+         %12 = OpLabel
+         %13 = OpLoad %7 %10
+         %16 = OpFAdd %7 %13 %15
+               OpReturnValue %16
+               OpFunctionEnd