Fix parsing error with structs containing arrays.
Previously, 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];`.
This is now fixed and our test case runs as expected.
Change-Id: I5b4a617c58cdfb83face651effd42770a1f68638
Bug: oss-fuzz:37622
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/441879
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index 316c0fd..3a3ae6a 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -473,6 +473,7 @@
const ASTNode::VarData& vd = var.getVarData();
// Read array size if one is present.
+ const Type* fieldType = type;
if (vd.fIsArray) {
const ASTNode& size = *var.begin();
if (!size || size.fKind != ASTNode::Kind::kInt) {
@@ -485,10 +486,10 @@
}
// Add the array dimensions to our type.
int arraySize = size.getInt();
- type = fSymbols.addArrayDimension(type, arraySize);
+ fieldType = fSymbols.addArrayDimension(fieldType, arraySize);
}
- fields.push_back(Type::Field(modifiers, vd.fName, type));
+ fields.push_back(Type::Field(modifiers, vd.fName, fieldType));
if (vd.fIsArray ? var.begin()->fNext : var.fFirstChild) {
this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
}
diff --git a/tests/SkSLTest.cpp b/tests/SkSLTest.cpp
index 8fc4c75..7eeda17 100644
--- a/tests/SkSLTest.cpp
+++ b/tests/SkSLTest.cpp
@@ -284,6 +284,7 @@
SKSL_TEST(SkSLStackingVectorCasts, "shared/StackingVectorCasts.sksl")
SKSL_TEST(SkSLStaticIf, "shared/StaticIf.sksl")
SKSL_TEST_ES3(SkSLStaticSwitch, "shared/StaticSwitch.sksl")
+SKSL_TEST(SkSLStructArrayFollowedByScalar, "shared/StructArrayFollowedByScalar.sksl")
SKSL_TEST(SkSLStructsInFunctions, "shared/StructsInFunctions.sksl")
SKSL_TEST(SkSLSwizzleBoolConstants, "shared/SwizzleBoolConstants.sksl")
SKSL_TEST(SkSLSwizzleByConstantIndex, "shared/SwizzleByConstantIndex.sksl")
diff --git a/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag b/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag
index 056c845..67d0fc9 100644
--- a/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag
+++ b/tests/sksl/shared/StructArrayFollowedByScalar.asm.frag
@@ -1,4 +1,82 @@
-### Compilation failed:
-
-error: 10: type mismatch: '=' cannot operate on 'half[3]', 'int'
-1 error
+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 %S "S"
+OpMemberName %S 0 "rgb"
+OpMemberName %S 1 "a"
+OpName %s "s"
+OpDecorate %sk_FragColor RelaxedPrecision
+OpDecorate %sk_FragColor Location 0
+OpDecorate %sk_FragColor Index 0
+OpDecorate %sk_Clockwise BuiltIn FrontFacing
+OpDecorate %_arr_float_int_3 ArrayStride 16
+OpMemberDecorate %S 0 Offset 0
+OpMemberDecorate %S 0 RelaxedPrecision
+OpMemberDecorate %S 1 Offset 48
+OpMemberDecorate %S 1 RelaxedPrecision
+OpDecorate %39 RelaxedPrecision
+OpDecorate %41 RelaxedPrecision
+OpDecorate %43 RelaxedPrecision
+OpDecorate %45 RelaxedPrecision
+OpDecorate %46 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
+%S = OpTypeStruct %_arr_float_int_3 %float
+%_ptr_Function_S = OpTypePointer Function %S
+%int_0 = OpConstant %int 0
+%_ptr_Function_float = OpTypePointer Function %float
+%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
+%s = OpVariable %_ptr_Function_S Function
+%30 = OpAccessChain %_ptr_Function_float %s %int_0 %int_0
+OpStore %30 %float_0
+%34 = OpAccessChain %_ptr_Function_float %s %int_0 %int_1
+OpStore %34 %float_1
+%36 = OpAccessChain %_ptr_Function_float %s %int_0 %int_2
+OpStore %36 %float_0
+%37 = OpAccessChain %_ptr_Function_float %s %int_1
+OpStore %37 %float_1
+%38 = OpAccessChain %_ptr_Function_float %s %int_0 %int_0
+%39 = OpLoad %float %38
+%40 = OpAccessChain %_ptr_Function_float %s %int_0 %int_1
+%41 = OpLoad %float %40
+%42 = OpAccessChain %_ptr_Function_float %s %int_0 %int_2
+%43 = OpLoad %float %42
+%44 = OpAccessChain %_ptr_Function_float %s %int_1
+%45 = OpLoad %float %44
+%46 = OpCompositeConstruct %v4float %39 %41 %43 %45
+OpReturnValue %46
+OpFunctionEnd
diff --git a/tests/sksl/shared/StructArrayFollowedByScalar.glsl b/tests/sksl/shared/StructArrayFollowedByScalar.glsl
index 056c845..a8d87c5 100644
--- a/tests/sksl/shared/StructArrayFollowedByScalar.glsl
+++ b/tests/sksl/shared/StructArrayFollowedByScalar.glsl
@@ -1,4 +1,14 @@
-### Compilation failed:
-error: 10: type mismatch: '=' cannot operate on 'half[3]', 'int'
-1 error
+out vec4 sk_FragColor;
+struct S {
+ float rgb[3];
+ float a;
+};
+vec4 main() {
+ S s;
+ s.rgb[0] = 0.0;
+ s.rgb[1] = 1.0;
+ s.rgb[2] = 0.0;
+ s.a = 1.0;
+ return vec4(s.rgb[0], s.rgb[1], s.rgb[2], s.a);
+}
diff --git a/tests/sksl/shared/StructArrayFollowedByScalar.metal b/tests/sksl/shared/StructArrayFollowedByScalar.metal
index 056c845..8f4b4f3 100644
--- a/tests/sksl/shared/StructArrayFollowedByScalar.metal
+++ b/tests/sksl/shared/StructArrayFollowedByScalar.metal
@@ -1,4 +1,23 @@
-### Compilation failed:
-
-error: 10: type mismatch: '=' cannot operate on 'half[3]', 'int'
-1 error
+#include <metal_stdlib>
+#include <simd/simd.h>
+using namespace metal;
+struct S {
+ array<float, 3> rgb;
+ float a;
+};
+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;
+ S s;
+ s.rgb[0] = 0.0;
+ s.rgb[1] = 1.0;
+ s.rgb[2] = 0.0;
+ s.a = 1.0;
+ _out.sk_FragColor = float4(s.rgb[0], s.rgb[1], s.rgb[2], s.a);
+ return _out;
+}