Demonstrate parsing error with structs and arrays.

The fuzzer detected a serious parsing error; a struct containing a
vardecl with multiple declarations would interpret arrays incorrectly.
An array would be applied to ALL variables in the decl after its initial
appearance. That is, `int w, x[10], y, z;` would be interpreted as
`int w, x[10], y[10], z[10];`. The fuzzer caught this by putting two
arrayed variables in a row; the second variable was interpreted as a
nested array, which led to an assertion.

This CL contains a simple hand-written test case demonstrating the bug,
with the fix coming in a followup.

Change-Id: I42d7372ba77fa1528ae24eb8c29a2e5903784139
Bug: oss-fuzz:37622
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/441878
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 51d7993..6338d74 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -282,6 +282,7 @@
   "/sksl/shared/ArrayCast.sksl",
   "/sksl/shared/ArrayComparison.sksl",
   "/sksl/shared/ArrayConstructors.sksl",
+  "/sksl/shared/ArrayFollowedByScalar.sksl",
   "/sksl/shared/ArrayIndexTypes.sksl",
   "/sksl/shared/ArrayNarrowingConversions.sksl",
   "/sksl/shared/ArrayTypes.sksl",
@@ -380,6 +381,7 @@
   "/sksl/shared/StaticSwitchWithFallthroughB.sksl",
   "/sksl/shared/StaticSwitchWithStaticConditionalBreak.sksl",
   "/sksl/shared/StaticSwitchWithStaticConditionalBreakInsideBlock.sksl",
+  "/sksl/shared/StructArrayFollowedByScalar.sksl",
   "/sksl/shared/Structs.sksl",
   "/sksl/shared/StructsInFunctions.sksl",
   "/sksl/shared/StructMaxDepth.sksl",
diff --git a/resources/sksl/shared/ArrayFollowedByScalar.sksl b/resources/sksl/shared/ArrayFollowedByScalar.sksl
new file mode 100644
index 0000000..1d9dce0
--- /dev/null
+++ b/resources/sksl/shared/ArrayFollowedByScalar.sksl
@@ -0,0 +1,8 @@
+half4 main(float2 coords) {
+    half rgb[3], a;
+    rgb[0] = 0;
+    rgb[1] = 1;
+    rgb[2] = 0;
+    a = 1;
+    return half4(rgb[0], rgb[1], rgb[2], a);
+}
diff --git a/resources/sksl/shared/StructArrayFollowedByScalar.sksl b/resources/sksl/shared/StructArrayFollowedByScalar.sksl
new file mode 100644
index 0000000..67bf355
--- /dev/null
+++ b/resources/sksl/shared/StructArrayFollowedByScalar.sksl
@@ -0,0 +1,12 @@
+struct S {
+    half rgb[3], a;
+};
+
+half4 main(float2 coords) {
+    S s;
+    s.rgb[0] = 0;
+    s.rgb[1] = 1;
+    s.rgb[2] = 0;
+    s.a = 1;
+    return half4(s.rgb[0], s.rgb[1], s.rgb[2], s.a);
+}
diff --git a/tests/SkSLTest.cpp b/tests/SkSLTest.cpp
index c5e7f7f..8fc4c75 100644
--- a/tests/SkSLTest.cpp
+++ b/tests/SkSLTest.cpp
@@ -233,6 +233,7 @@
 SKSL_TEST_ES3(SkSLArrayComparison,             "shared/ArrayComparison.sksl")
 SKSL_TEST_ES3(SkSLArrayConstructors,           "shared/ArrayConstructors.sksl")
 SKSL_TEST_ES3(SkSLArrayCast,                   "shared/ArrayCast.sksl")
+SKSL_TEST_ES3(SkSLArrayFollowedByScalar,       "shared/ArrayFollowedByScalar.sksl")
 SKSL_TEST(SkSLArrayTypes,                      "shared/ArrayTypes.sksl")
 SKSL_TEST(SkSLAssignment,                      "shared/Assignment.sksl")
 SKSL_TEST(SkSLCastsRoundTowardZero,            "shared/CastsRoundTowardZero.sksl")
diff --git a/tests/sksl/shared/ArrayFollowedByScalar.asm.frag b/tests/sksl/shared/ArrayFollowedByScalar.asm.frag
new file mode 100644
index 0000000..d2e794e
--- /dev/null
+++ b/tests/sksl/shared/ArrayFollowedByScalar.asm.frag
@@ -0,0 +1,76 @@
+OpCapability Shader
+%1 = OpExtInstImport "GLSL.std.450"
+OpMemoryModel Logical GLSL450
+OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
+OpExecutionMode %_entrypoint_v OriginUpperLeft
+OpName %sk_FragColor "sk_FragColor"
+OpName %sk_Clockwise "sk_Clockwise"
+OpName %_entrypoint_v "_entrypoint_v"
+OpName %main "main"
+OpName %rgb "rgb"
+OpName %a "a"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpDecorate %rgb RelaxedPrecision
+OpDecorate %_arr_float_int_3 ArrayStride 16
+OpDecorate %a RelaxedPrecision
+OpDecorate %38 RelaxedPrecision
+OpDecorate %40 RelaxedPrecision
+OpDecorate %42 RelaxedPrecision
+OpDecorate %43 RelaxedPrecision
+OpDecorate %44 RelaxedPrecision
+%float = OpTypeFloat 32
+%v4float = OpTypeVector %float 4
+%_ptr_Output_v4float = OpTypePointer Output %v4float
+%sk_FragColor = OpVariable %_ptr_Output_v4float Output
+%bool = OpTypeBool
+%_ptr_Input_bool = OpTypePointer Input %bool
+%sk_Clockwise = OpVariable %_ptr_Input_bool Input
+%void = OpTypeVoid
+%12 = OpTypeFunction %void
+%v2float = OpTypeVector %float 2
+%float_0 = OpConstant %float 0
+%16 = OpConstantComposite %v2float %float_0 %float_0
+%_ptr_Function_v2float = OpTypePointer Function %v2float
+%20 = OpTypeFunction %v4float %_ptr_Function_v2float
+%int = OpTypeInt 32 1
+%int_3 = OpConstant %int 3
+%_arr_float_int_3 = OpTypeArray %float %int_3
+%_ptr_Function__arr_float_int_3 = OpTypePointer Function %_arr_float_int_3
+%_ptr_Function_float = OpTypePointer Function %float
+%int_0 = OpConstant %int 0
+%float_1 = OpConstant %float 1
+%int_1 = OpConstant %int 1
+%int_2 = OpConstant %int 2
+%_entrypoint_v = OpFunction %void None %12
+%13 = OpLabel
+%17 = OpVariable %_ptr_Function_v2float Function
+OpStore %17 %16
+%19 = OpFunctionCall %v4float %main %17
+OpStore %sk_FragColor %19
+OpReturn
+OpFunctionEnd
+%main = OpFunction %v4float None %20
+%21 = OpFunctionParameter %_ptr_Function_v2float
+%22 = OpLabel
+%rgb = OpVariable %_ptr_Function__arr_float_int_3 Function
+%a = OpVariable %_ptr_Function_float Function
+%31 = OpAccessChain %_ptr_Function_float %rgb %int_0
+OpStore %31 %float_0
+%34 = OpAccessChain %_ptr_Function_float %rgb %int_1
+OpStore %34 %float_1
+%36 = OpAccessChain %_ptr_Function_float %rgb %int_2
+OpStore %36 %float_0
+OpStore %a %float_1
+%37 = OpAccessChain %_ptr_Function_float %rgb %int_0
+%38 = OpLoad %float %37
+%39 = OpAccessChain %_ptr_Function_float %rgb %int_1
+%40 = OpLoad %float %39
+%41 = OpAccessChain %_ptr_Function_float %rgb %int_2
+%42 = OpLoad %float %41
+%43 = OpLoad %float %a
+%44 = OpCompositeConstruct %v4float %38 %40 %42 %43
+OpReturnValue %44
+OpFunctionEnd
diff --git a/tests/sksl/shared/ArrayFollowedByScalar.glsl b/tests/sksl/shared/ArrayFollowedByScalar.glsl
new file mode 100644
index 0000000..c9508ae
--- /dev/null
+++ b/tests/sksl/shared/ArrayFollowedByScalar.glsl
@@ -0,0 +1,11 @@
+
+out vec4 sk_FragColor;
+vec4 main() {
+    float rgb[3];
+    float a;
+    rgb[0] = 0.0;
+    rgb[1] = 1.0;
+    rgb[2] = 0.0;
+    a = 1.0;
+    return vec4(rgb[0], rgb[1], rgb[2], a);
+}
diff --git a/tests/sksl/shared/ArrayFollowedByScalar.metal b/tests/sksl/shared/ArrayFollowedByScalar.metal
new file mode 100644
index 0000000..935e8eb
--- /dev/null
+++ b/tests/sksl/shared/ArrayFollowedByScalar.metal
@@ -0,0 +1,20 @@
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct Inputs {
+};
+struct Outputs {
+    float4 sk_FragColor [[color(0)]];
+};
+fragment Outputs fragmentMain(Inputs _in [[stage_in]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
+    Outputs _out;
+    (void)_out;
+    array<float, 3> rgb;
+    float a;
+    rgb[0] = 0.0;
+    rgb[1] = 1.0;
+    rgb[2] = 0.0;
+    a = 1.0;
+    _out.sk_FragColor = float4(rgb[0], rgb[1], rgb[2], a);
+    return _out;
+}
diff --git a/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag b/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag
new file mode 100644
index 0000000..056c845
--- /dev/null
+++ b/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag
@@ -0,0 +1,4 @@
+### Compilation failed:
+
+error: 10: type mismatch: '=' cannot operate on 'half[3]', 'int'
+1 error
diff --git a/tests/sksl/shared/StructArrayFollowedByScalar.glsl b/tests/sksl/shared/StructArrayFollowedByScalar.glsl
new file mode 100644
index 0000000..056c845
--- /dev/null
+++ b/tests/sksl/shared/StructArrayFollowedByScalar.glsl
@@ -0,0 +1,4 @@
+### Compilation failed:
+
+error: 10: type mismatch: '=' cannot operate on 'half[3]', 'int'
+1 error
diff --git a/tests/sksl/shared/StructArrayFollowedByScalar.metal b/tests/sksl/shared/StructArrayFollowedByScalar.metal
new file mode 100644
index 0000000..056c845
--- /dev/null
+++ b/tests/sksl/shared/StructArrayFollowedByScalar.metal
@@ -0,0 +1,4 @@
+### Compilation failed:
+
+error: 10: type mismatch: '=' cannot operate on 'half[3]', 'int'
+1 error