From 1d585ac8bdd491b1ef9bb00ce8fdce9ece0a8748 Mon Sep 17 00:00:00 2001
From: John Kessenich <cepheus@frii.com>
Date: Sat, 20 May 2017 12:14:13 -0600
Subject: [PATCH] SPV: Correctly enforce 'location' presence on in/out blocks.

Blocks have this on members, not the object.
---
 Test/baseResults/spv.noLocation.vert.out   |  5 ++++-
 Test/spv.noLocation.vert                   | 19 +++++++++++++++++++
 glslang/MachineIndependent/ParseHelper.cpp | 15 ++++++++++-----
 3 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/Test/baseResults/spv.noLocation.vert.out b/Test/baseResults/spv.noLocation.vert.out
index 43e2534c7..7bd74679f 100644
--- a/Test/baseResults/spv.noLocation.vert.out
+++ b/Test/baseResults/spv.noLocation.vert.out
@@ -2,7 +2,10 @@ spv.noLocation.vert
 Warning, version 450 is not yet complete; most version-specific features are present, but some are missing.
 ERROR: spv.noLocation.vert:4: 'location' : SPIR-V requires location for user input/output 
 ERROR: spv.noLocation.vert:8: 'location' : SPIR-V requires location for user input/output 
-ERROR: 2 compilation errors.  No code generated.
+ERROR: spv.noLocation.vert:19: 'location' : SPIR-V requires location for user input/output 
+ERROR: spv.noLocation.vert:25: 'location' : SPIR-V requires location for user input/output 
+ERROR: spv.noLocation.vert:29: 'location' : SPIR-V requires location for user input/output 
+ERROR: 5 compilation errors.  No code generated.
 
 
 SPIR-V is not generated for failed compile or link
diff --git a/Test/spv.noLocation.vert b/Test/spv.noLocation.vert
index e3c02eedc..dd495b7a7 100644
--- a/Test/spv.noLocation.vert
+++ b/Test/spv.noLocation.vert
@@ -8,6 +8,25 @@ layout(location = 1) out vec4 out1;
 out vec4 out2;
 layout(location = 3) out vec4 out3;
 
+layout(location = 10) out inb1 { 
+    vec4 a;
+    vec4 b;
+} inbi1;
+out inb2 { 
+    layout(location = 12) vec4 a;
+    layout(location = 13) vec4 b;
+} inbi2;
+out inb3 {
+    vec4 a;
+    vec4 b;
+} inbi3;
+
+layout(location = 14) out struct S1 { vec4 a; } s1;
+out struct S2 { vec4 a; } s2;
+
+struct SS { int a; };
+out layout(location = 15) SS ss1;
+out SS ss2;
 
 void main()
 {
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index b3dbeda2f..ebe5b5070 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -4332,14 +4332,19 @@ void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symb
         default:
             break;
         }
-    } else if (spvVersion.spv > 0) {
+    }
+
+    // user-variable location check, which are required for SPIR-V in/out:
+    //  - variables have it directly,
+    //  - blocks have it on each member (already enforced), so check first one
+    if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone &&
+        !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) {
+
         switch (qualifier.storage) {
         case EvqVaryingIn:
         case EvqVaryingOut:
-            if (! parsingBuiltins && qualifier.builtIn == EbvNone) {
-                if (!intermediate.getAutoMapLocations())
-                    error(loc, "SPIR-V requires location for user input/output", "location", "");
-            }
+            if (type.getBasicType() != EbtBlock || !(*type.getStruct())[0].type->getQualifier().hasLocation())
+                error(loc, "SPIR-V requires location for user input/output", "location", "");
             break;
         default:
             break;
-- 
GitLab