HLSL: Insert return statements into functions that are missing them.

It's allowed to not have all code paths return a value in ESSL but the HLSL
compiler detects this and generates an error.  Work around this by adding
dummy return statements at the end of each function that doesn't have one.

TEST=deqp/data/gles2/shaders/functions.html

BUG=angleproject:1015
BUG=478572

Change-Id: I2913f90f0994d4caf25cc43b16b9fc4e9efb19a5
Reviewed-on: https://chromium-review.googlesource.com/362085
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
index d67bb5e..3fc0bf1 100644
--- a/src/tests/gl_tests/GLSLTest.cpp
+++ b/src/tests/gl_tests/GLSLTest.cpp
@@ -906,6 +906,159 @@
     EXPECT_NE(0u, program);
 }
 
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnFloat)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "float f() { if (v_varying > 0.0) return 1.0; }\n"
+        "void main() { gl_Position = vec4(f(), 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnVec2)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "vec2 f() { if (v_varying > 0.0) return vec2(1.0, 1.0); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnVec3)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "vec3 f() { if (v_varying > 0.0) return vec3(1.0, 1.0, 1.0); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnVec4)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "vec4 f() { if (v_varying > 0.0) return vec4(1.0, 1.0, 1.0, 1.0); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnIVec4)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "ivec4 f() { if (v_varying > 0.0) return ivec4(1, 1, 1, 1); }\n"
+        "void main() { gl_Position = vec4(f().x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnMat4)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "mat4 f() { if (v_varying > 0.0) return mat4(1.0); }\n"
+        "void main() { gl_Position = vec4(f()[0][0], 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest, MissingReturnStruct)
+{
+    const std::string vertexShaderSource =
+        "varying float v_varying;\n"
+        "struct s { float a; int b; vec2 c; };\n"
+        "s f() { if (v_varying > 0.0) return s(1.0, 1, vec2(1.0, 1.0)); }\n"
+        "void main() { gl_Position = vec4(f().a, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "precision mediump float;\n"
+        "void main() { gl_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest_ES3, MissingReturnArray)
+{
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in float v_varying;\n"
+        "vec2[2] f() { if (v_varying > 0.0) { return vec2[2](vec2(1.0, 1.0), vec2(1.0, 1.0)); } }\n"
+        "void main() { gl_Position = vec4(f()[0].x, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
+// Verify that functions without return statements still compile
+TEST_P(GLSLTest_ES3, MissingReturnArrayOfStructs)
+{
+    const std::string vertexShaderSource =
+        "#version 300 es\n"
+        "in float v_varying;\n"
+        "struct s { float a; int b; vec2 c; };\n"
+        "s[2] f() { if (v_varying > 0.0) { return s[2](s(1.0, 1, vec2(1.0, 1.0)), s(1.0, 1, "
+        "vec2(1.0, 1.0))); } }\n"
+        "void main() { gl_Position = vec4(f()[0].a, 0, 0, 1); }\n";
+
+    const std::string fragmentShaderSource =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "out vec4 my_FragColor;\n"
+        "void main() { my_FragColor = vec4(0, 0, 0, 1); }\n";
+
+    GLuint program = CompileProgram(vertexShaderSource, fragmentShaderSource);
+    EXPECT_NE(0u, program);
+}
+
 // Verify that using invariant(all) in both shaders fails in ESSL 3.00.
 TEST_P(GLSLTest_ES3, InvariantAllBoth)
 {