Make all fragment shader out variables require location layout qualifier

Make all fragment shader out variables require location layout
qualifier. Previously, the last variable did not need a location layout
qualifier if the previous variables had those.

TEST=angle_unittests
BUG=angleproject:1070

Change-Id: Ifb66ee52b811409f5278eaad330d6cd9b8ea059f
Reviewed-on: https://chromium-review.googlesource.com/287100
Tested-by: Kimmo Kinnunen <kkinnunen@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/ValidateOutputs.cpp b/src/compiler/translator/ValidateOutputs.cpp
index 614d790..6976309 100644
--- a/src/compiler/translator/ValidateOutputs.cpp
+++ b/src/compiler/translator/ValidateOutputs.cpp
@@ -32,12 +32,13 @@
     {
         const TType &type = symbol->getType();
         const int location = type.getLayoutQualifier().location;
+        const bool isUnspecifiedOutputLocation = location == -1;
 
-        if (mHasUnspecifiedOutputLocation)
+        if (mHasUnspecifiedOutputLocation || (isUnspecifiedOutputLocation && !mOutputMap.empty()))
         {
             error(symbol->getLine(), "must explicitly specify all locations when using multiple fragment outputs", name.c_str());
         }
-        else if (location == -1)
+        else if (isUnspecifiedOutputLocation)
         {
             mHasUnspecifiedOutputLocation = true;
         }
diff --git a/src/tests/compiler_tests/MalformedShader_test.cpp b/src/tests/compiler_tests/MalformedShader_test.cpp
index 9a9a46d..cee1335 100644
--- a/src/tests/compiler_tests/MalformedShader_test.cpp
+++ b/src/tests/compiler_tests/MalformedShader_test.cpp
@@ -689,6 +689,64 @@
     }
 }
 
+// If there is more than one output, the location must be specified for all outputs.
+// (ESSL 3.00.04 section 4.3.8.2)
+TEST_F(MalformedShaderTest, TwoOutputsNoLayoutQualifiers)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "out vec4 my_FragColor;\n"
+        "out vec4 my_SecondaryFragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(1.0);\n"
+        "    my_SecondaryFragColor = vec4(0.5);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// (ESSL 3.00.04 section 4.3.8.2)
+TEST_F(MalformedShaderTest, TwoOutputsFirstLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "layout(location = 0) out vec4 my_FragColor;\n"
+        "out vec4 my_SecondaryFragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(1.0);\n"
+        "    my_SecondaryFragColor = vec4(0.5);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
+// (ESSL 3.00.04 section 4.3.8.2)
+TEST_F(MalformedShaderTest, TwoOutputsSecondLayoutQualifier)
+{
+    const std::string &shaderString =
+        "#version 300 es\n"
+        "precision mediump float;\n"
+        "uniform vec4 u;\n"
+        "out vec4 my_FragColor;\n"
+        "layout(location = 0) out vec4 my_SecondaryFragColor;\n"
+        "void main() {\n"
+        "    my_FragColor = vec4(1.0);\n"
+        "    my_SecondaryFragColor = vec4(0.5);\n"
+        "}\n";
+    if (compile(shaderString))
+    {
+        FAIL() << "Shader compilation succeeded, expecting failure " << mInfoLog;
+    }
+}
+
 // Uniforms can be arrays (ESSL 3.00 section 4.3.5)
 TEST_F(MalformedShaderTest, UniformArray)
 {