diff --git a/Test/400.tesc b/Test/400.tesc
index 8c7669409cc3d7a3949ece9011ec61450962d195..e4463acda627a2168ecbe370074ebab744eaa9d8 100644
--- a/Test/400.tesc
+++ b/Test/400.tesc
@@ -35,3 +35,11 @@ void main()
     gl_TessLevelOuter[3] = 3.2;
     gl_TessLevelInner[1] = 1.3;
 }
+
+layout(vertices = 4) in;    // ERROR
+layout(vertices = 5) out;   // ERROR
+
+void foo()
+{
+    gl_out[4].gl_PointSize;  // ERROR
+}
\ No newline at end of file
diff --git a/Test/410.tesc b/Test/410.tesc
new file mode 100644
index 0000000000000000000000000000000000000000..d96a27003e0502e3dec785d5b2cce9d9aa5fe526
--- /dev/null
+++ b/Test/410.tesc
@@ -0,0 +1,11 @@
+#version 400 core
+
+// no layout(vertices = ...) out;
+int outa[gl_out.length()];  // ERROR
+
+patch out vec4 patchOut;
+
+void main()
+{
+
+}
diff --git a/Test/420.tesc b/Test/420.tesc
new file mode 100644
index 0000000000000000000000000000000000000000..e2892380097d3207d424d78d4e7442a7a219cdcf
--- /dev/null
+++ b/Test/420.tesc
@@ -0,0 +1,27 @@
+#version 400 core
+
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(vertices = 4) out;
+
+out gl_PerVertex {
+    vec4 gl_Position;
+} gl_out[3];                 // ERROR, wrong size
+
+out int a[gl_out.length()];
+out int outb[5];             // ERROR, wrong size
+out int outc[];
+
+void main()
+{
+    vec4 p = gl_in[1].gl_Position;
+    float ps = gl_in[1].gl_PointSize;
+    float cd = gl_in[1].gl_ClipDistance[2];
+
+    int pvi = gl_PatchVerticesIn;
+    int pid = gl_PrimitiveID;
+    int iid = gl_InvocationID;
+
+    gl_out[1].gl_Position = p;
+    gl_out[1].gl_PointSize = ps;        // ERROR
+}
diff --git a/Test/420_size_gl_in.geom b/Test/420_size_gl_in.geom
new file mode 100644
index 0000000000000000000000000000000000000000..fd6d134a59ac44e5004e1e197392ac7304859c2b
--- /dev/null
+++ b/Test/420_size_gl_in.geom
@@ -0,0 +1,21 @@
+#version 420 core
+
+// testing input arrays without a gl_in[] block redeclaration, see 400.geom for with
+
+int i;
+
+layout(triangles) in;
+in vec4 colorun[];
+in vec4 color3[3];
+
+void foo()
+{
+    gl_in.length();
+    gl_in[1].gl_Position;
+    gl_in.length();
+    gl_in[i].gl_Position;
+}
+
+in gl_PerVertex {  // ERROR, already used
+    vec4 gl_Position;
+} gl_in[];
diff --git a/Test/baseResults/400.geom.out b/Test/baseResults/400.geom.out
index 141a0c797aae0edf6d7903db2b737d0fa811c33a..a9d74083f36d1a1e35f01fe7862f2dd7dd045729 100644
--- a/Test/baseResults/400.geom.out
+++ b/Test/baseResults/400.geom.out
@@ -4,8 +4,8 @@ ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier
 ERROR: 0:20: 'patch' : not supported in this stage: geometry
 ERROR: 0:20: 'gl_PointSize' : cannot add layout to redeclared block member 
 ERROR: 0:20: 'gl_PointSize' : cannot add patch to redeclared block member 
-ERROR: 0:25: 'length' :  array must be declared with a size before using this method
-ERROR: 0:36: 'length' :  array must be declared with a size before using this method
+ERROR: 0:25: 'length' :  array must first be sized by a redeclaration or layout qualifier
+ERROR: 0:36: 'length' :  array must first be sized by a redeclaration or layout qualifier
 ERROR: 0:40: 'triangles' : inconsistent input primitive for array size colorBad
 ERROR: 0:44: 'triangles' : inconsistent input primitive for array size colorbad2
 ERROR: 0:56: 'location' : repeated use of location 4
@@ -81,7 +81,7 @@ ERROR: node is still EOpNull!
 
 Linked geometry stage:
 
-ERROR: Linking geometry stage: At least one geometry shader must specify an output layout primitive
+ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
 
 invocations = 4
 max_vertices = 127
diff --git a/Test/baseResults/400.tesc.out b/Test/baseResults/400.tesc.out
index 490ed3a78b39d605eae35fd36864e3112c9daddc..3e10c21f10e7729fccb3374068a46a6a9f1481fe 100644
--- a/Test/baseResults/400.tesc.out
+++ b/Test/baseResults/400.tesc.out
@@ -1,11 +1,13 @@
 400.tesc
 Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
-ERROR: 0:4: 'length' :  array must be declared with a size before using this method
 ERROR: 0:6: 'quads' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) 
 ERROR: 0:7: 'ccw' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) 
 ERROR: 0:8: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignemnt (e.g., binding = 4) 
 ERROR: 0:10: 'patch' : can only use on output in tessellation-control shader 
-ERROR: 5 compilation errors.  No code generated.
+ERROR: 0:39: 'vertices' : can only apply to 'out' 
+ERROR: 0:40: 'vertices' : cannot change previously set layout value 
+ERROR: 0:44: '[' :  array index out of range '4'
+ERROR: 7 compilation errors.  No code generated.
 
 
 vertices = 4
@@ -67,7 +69,7 @@ ERROR: node is still EOpNull!
 0:31      move second child to first child (4-component vector of float)
 0:31        gl_Position: direct index for structure (4-component vector of float)
 0:31          direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
-0:31            'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:31            'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
 0:31            Constant:
 0:31              1 (const int)
 0:31          Constant:
@@ -76,7 +78,7 @@ ERROR: node is still EOpNull!
 0:32      move second child to first child (float)
 0:32        gl_PointSize: direct index for structure (float)
 0:32          direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
-0:32            'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:32            'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
 0:32            Constant:
 0:32              1 (const int)
 0:32          Constant:
@@ -86,7 +88,7 @@ ERROR: node is still EOpNull!
 0:33        direct index (float)
 0:33          gl_ClipDistance: direct index for structure (unsized array of float)
 0:33            direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
-0:33              'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:33              'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
 0:33              Constant:
 0:33                1 (const int)
 0:33            Constant:
@@ -108,11 +110,21 @@ ERROR: node is still EOpNull!
 0:36            1 (const int)
 0:36        Constant:
 0:36          1.300000
+0:42  Function Definition: foo( (void)
+0:42    Function Parameters: 
+0:44    Sequence
+0:44      gl_PointSize: direct index for structure (float)
+0:44        direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:44          'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:44          Constant:
+0:44            4 (const int)
+0:44        Constant:
+0:44          1 (const int)
 0:?   Linker Objects
-0:?     'outa' (1-element array of int)
+0:?     'outa' (4-element array of int)
 0:?     'patchIn' (patch in 4-component vector of float)
 0:?     'patchOut' (patch out 4-component vector of float)
-0:?     'gl_out' (out unsized array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:?     'gl_out' (out 4-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
 
 
 Linked tessellation control stage:
diff --git a/Test/baseResults/410.geom.out b/Test/baseResults/410.geom.out
index 1a4c58030a3286375fb7f70fd1d532d79055df96..1eaeec69058ee8a455ff7cd5e9ac40edcb339f32 100644
--- a/Test/baseResults/410.geom.out
+++ b/Test/baseResults/410.geom.out
@@ -52,9 +52,9 @@ ERROR: node is still EOpNull!
 
 Linked geometry stage:
 
-ERROR: Linking geometry stage: At least one geometry shader must specify an input layout primitive
-ERROR: Linking geometry stage: At least one geometry shader must specify an output layout primitive
-ERROR: Linking geometry stage: At least one geometry shader must specify a layout(max_vertices = value)
+ERROR: Linking geometry stage: At least one shader must specify an input layout primitive
+ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
+ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
 
 invocations = 0
 max_vertices = 0
diff --git a/Test/baseResults/410.tesc.out b/Test/baseResults/410.tesc.out
new file mode 100644
index 0000000000000000000000000000000000000000..832ee90cf8172c7cbccf19af529546bdf83dcfcb
--- /dev/null
+++ b/Test/baseResults/410.tesc.out
@@ -0,0 +1,21 @@
+410.tesc
+Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
+ERROR: 0:4: 'length' :  array must first be sized by a redeclaration or layout qualifier
+ERROR: 1 compilation errors.  No code generated.
+
+
+vertices = 0
+ERROR: node is still EOpNull!
+0:8  Function Definition: main( (void)
+0:8    Function Parameters: 
+0:?   Linker Objects
+0:?     'outa' (1-element array of int)
+0:?     'patchOut' (patch out 4-component vector of float)
+
+
+Linked tessellation control stage:
+
+ERROR: Linking tessellation control stage: At least one shader must specify an output layout(vertices=...)
+
+vertices = 0
+
diff --git a/Test/baseResults/420.geom.out b/Test/baseResults/420.geom.out
index 10af91375cc3b5c4ec0f4ed6c3d52e406e4389ac..fc6e6c9cca16cd149d5ff8f81366f208200d700d 100644
--- a/Test/baseResults/420.geom.out
+++ b/Test/baseResults/420.geom.out
@@ -1,7 +1,7 @@
 420.geom
 Warning, version 420 is not yet complete; some version-specific features are present, but many are missing.
-ERROR: 0:9: 'length' :  array must be declared with a size before using this method
-ERROR: 0:11: '[' :  array must be redeclared with a size before being indexed with a variable
+ERROR: 0:9: 'length' :  array must first be sized by a redeclaration or layout qualifier
+ERROR: 0:11: '[' :  array must be sized by a redeclaration or layout qualifier before being indexed with a variable
 ERROR: 0:42: 'assign' :  l-value required (can't modify a const)
 ERROR: 0:43: 'assign' :  l-value required "v4" (can't modify a uniform)
 ERROR: 0:48: 'gl_PointSize' : cannot change arrayness of redeclared block member 
@@ -123,8 +123,8 @@ ERROR: node is still EOpNull!
 Linked geometry stage:
 
 ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point
-ERROR: Linking geometry stage: At least one geometry shader must specify an output layout primitive
-ERROR: Linking geometry stage: At least one geometry shader must specify a layout(max_vertices = value)
+ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
+ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
 
 invocations = 0
 max_vertices = 0
diff --git a/Test/baseResults/420.tesc.out b/Test/baseResults/420.tesc.out
new file mode 100644
index 0000000000000000000000000000000000000000..4ffba0bac29ee0709db5135792602caef0818de3
--- /dev/null
+++ b/Test/baseResults/420.tesc.out
@@ -0,0 +1,85 @@
+420.tesc
+Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
+ERROR: 0:7: 'vertices' : inconsistent output number of vertices for array size gl_out
+ERROR: 0:11: 'vertices' : inconsistent output number of vertices for array size a
+ERROR: 0:12: 'vertices' : inconsistent output number of vertices for array size outb
+ERROR: 0:26: 'gl_PointSize' :  no such field in structure 
+ERROR: 0:26: 'assign' :  cannot convert from 'float' to 'block{gl_Position}'
+ERROR: 5 compilation errors.  No code generated.
+
+
+vertices = 4
+ERROR: node is still EOpNull!
+0:15  Function Definition: main( (void)
+0:15    Function Parameters: 
+0:17    Sequence
+0:17      Sequence
+0:17        move second child to first child (4-component vector of float)
+0:17          'p' (4-component vector of float)
+0:17          gl_Position: direct index for structure (4-component vector of float)
+0:17            direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:17              'gl_in' (in 32-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:17              Constant:
+0:17                1 (const int)
+0:17            Constant:
+0:17              0 (const int)
+0:18      Sequence
+0:18        move second child to first child (float)
+0:18          'ps' (float)
+0:18          gl_PointSize: direct index for structure (float)
+0:18            direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:18              'gl_in' (in 32-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:18              Constant:
+0:18                1 (const int)
+0:18            Constant:
+0:18              1 (const int)
+0:19      Sequence
+0:19        move second child to first child (float)
+0:19          'cd' (float)
+0:19          direct index (float)
+0:19            gl_ClipDistance: direct index for structure (unsized array of float)
+0:19              direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:19                'gl_in' (in 32-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:19                Constant:
+0:19                  1 (const int)
+0:19              Constant:
+0:19                2 (const int)
+0:19            Constant:
+0:19              2 (const int)
+0:21      Sequence
+0:21        move second child to first child (int)
+0:21          'pvi' (int)
+0:21          'gl_PatchVerticesIn' (in int)
+0:22      Sequence
+0:22        move second child to first child (int)
+0:22          'pid' (int)
+0:22          'gl_PrimitiveID' (in int)
+0:23      Sequence
+0:23        move second child to first child (int)
+0:23          'iid' (int)
+0:23          'gl_InvocationID' (in int)
+0:25      move second child to first child (4-component vector of float)
+0:25        gl_Position: direct index for structure (4-component vector of float)
+0:25          direct index (block{gl_Position})
+0:25            'gl_out' (out 3-element array of block{gl_Position})
+0:25            Constant:
+0:25              1 (const int)
+0:25          Constant:
+0:25            0 (const int)
+0:25        'p' (4-component vector of float)
+0:26      direct index (block{gl_Position})
+0:26        'gl_out' (out 3-element array of block{gl_Position})
+0:26        Constant:
+0:26          1 (const int)
+0:?   Linker Objects
+0:?     'gl_out' (out 3-element array of block{gl_Position})
+0:?     'a' (out 3-element array of int)
+0:?     'outb' (out 5-element array of int)
+0:?     'outc' (out 4-element array of int)
+
+
+Linked tessellation control stage:
+
+
+vertices = 4
+
diff --git a/Test/baseResults/420.tese.out b/Test/baseResults/420.tese.out
index 2df4c1575b31f0d27a40a034d06251d90dea22d8..71ddd93749af95ff6bdac4fce2dc550dcec69010 100644
--- a/Test/baseResults/420.tese.out
+++ b/Test/baseResults/420.tese.out
@@ -163,7 +163,7 @@ ERROR: node is still EOpNull!
 
 Linked tessellation evaluation stage:
 
-ERROR: Linking tessellation evaluation stage: At least one tessellation shader must specify an input layout primitive
+ERROR: Linking tessellation evaluation stage: At least one shader must specify an input layout primitive
 
 input primitive = none
 vertex spacing = equal_spacing
diff --git a/Test/baseResults/420_size_gl_in.geom.out b/Test/baseResults/420_size_gl_in.geom.out
new file mode 100644
index 0000000000000000000000000000000000000000..0915868635d4c1fcf6b80759cb567d1227cf21ac
--- /dev/null
+++ b/Test/baseResults/420_size_gl_in.geom.out
@@ -0,0 +1,49 @@
+420_size_gl_in.geom
+Warning, version 420 is not yet complete; some version-specific features are present, but many are missing.
+ERROR: 0:19: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use 
+ERROR: 1 compilation errors.  No code generated.
+
+
+invocations = 0
+max_vertices = 0
+input primitive = triangles
+output primitive = none
+ERROR: node is still EOpNull!
+0:11  Function Definition: foo( (void)
+0:11    Function Parameters: 
+0:13    Sequence
+0:13      Constant:
+0:13        3 (const int)
+0:14      gl_Position: direct index for structure (4-component vector of float)
+0:14        direct index (block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:14          'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:14          Constant:
+0:14            1 (const int)
+0:14        Constant:
+0:14          0 (const int)
+0:15      Constant:
+0:15        3 (const int)
+0:16      gl_Position: direct index for structure (4-component vector of float)
+0:16        indirect index (block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:16          'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+0:16          'i' (int)
+0:16        Constant:
+0:16          0 (const int)
+0:?   Linker Objects
+0:?     'i' (int)
+0:?     'colorun' (in 3-element array of 4-component vector of float)
+0:?     'color3' (in 3-element array of 4-component vector of float)
+0:?     'gl_in' (in 3-element array of block{gl_Position,gl_PointSize,gl_ClipDistance})
+
+
+Linked geometry stage:
+
+ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point
+ERROR: Linking geometry stage: At least one shader must specify an output layout primitive
+ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
+
+invocations = 0
+max_vertices = 0
+input primitive = triangles
+output primitive = none
+
diff --git a/Test/baseResults/mains1.frag.out b/Test/baseResults/mains1.frag.out
index 87d8800de04766d754a5ab9227fe3b10f396d81c..4510d7469f93de52aabcbb3e788af5b1f05853ca 100644
--- a/Test/baseResults/mains1.frag.out
+++ b/Test/baseResults/mains1.frag.out
@@ -44,8 +44,8 @@ Linked geometry stage:
 
 ERROR: Linking geometry stage: Contradictory output layout primitives
 ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point
-ERROR: Linking geometry stage: At least one geometry shader must specify an input layout primitive
-ERROR: Linking geometry stage: At least one geometry shader must specify a layout(max_vertices = value)
+ERROR: Linking geometry stage: At least one shader must specify an input layout primitive
+ERROR: Linking geometry stage: At least one shader must specify a layout(max_vertices = value)
 
 Linked fragment stage:
 
diff --git a/Test/testlist b/Test/testlist
index f32ea4ee5bfda61b2feba84c7b3056798517cc5c..ac63cbbf95d61bfd3dcb063f968e315644b1c8e7 100644
--- a/Test/testlist
+++ b/Test/testlist
@@ -49,7 +49,9 @@ tokenLength.vert
 300scope.vert
 400.frag
 420.vert
+420.tesc
 420.geom
+420_size_gl_in.geom
 430scope.vert
 lineContinuation100.vert
 lineContinuation.vert
@@ -58,6 +60,7 @@ numeral.frag
 400.tesc
 400.tese
 410.geom
+410.tesc
 420.tese
 430.vert
 430.comp
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index 92b2c479c0fcf6a29501929e0d2e749e81a04ec6..096b2511d00208f50bdbe335f836bbcbe62648e8 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build
 // going.  However, if it is not updated, it can be a version behind.
 
-#define GLSLANG_REVISION "24480"
-#define GLSLANG_DATE     "2013/12/11 15:38:19"
+#define GLSLANG_REVISION "24486"
+#define GLSLANG_DATE     "2013/12/11 18:25:37"
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index d413176fe9a2104d7d22c9585969f9cab0432fca..6e01da57138820e60425c29725acaf593f234d96 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -437,13 +437,21 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
         return intermediate.foldDereference(base, indexValue, loc);
     else {
         // at least one of base and index is variable...
+
+        if (isIoResizeArray(base->getType()))
+            handleIoResizeArrayAccess(loc, base);
+
         if (index->getQualifier().storage == EvqConst) {
             if (base->isArray() && base->getType().getArraySize() == 0)
                 updateMaxArraySize(loc, base, indexValue);
             result = intermediate.addIndex(EOpIndexDirect, base, index, loc);
         } else {
-            if (base->isArray() && base->getType().getArraySize() == 0)
-                error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
+            if (base->isArray() && base->getType().getArraySize() == 0) {
+                if (isIoResizeArray(base->getType()))
+                    error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
+                else
+                    error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
+            }
             if (base->getBasicType() == EbtBlock)
                 requireProfile(base->getLoc(), ~EEsProfile, "variable indexing block array");
             else if (language == EShLangFragment && base->getQualifier().isPipeOutput())
@@ -474,9 +482,6 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
 
         if (anyIndexLimits)
             handleIndexLimits(loc, base, index);
-
-        if (language == EShLangGeometry && base->isArray())
-            handleInputArrayAccess(loc, base);
     }
 
     return result;
@@ -523,62 +528,99 @@ void TParseContext::handleIndexLimits(TSourceLoc loc, TIntermTyped* base, TInter
     }
 }
 
-// Handle a dereference of a geometry shader input arrays.
-// See inputArrayNodeResizeList comment in ParseHelper.h.
-//
-void TParseContext::handleInputArrayAccess(TSourceLoc loc, TIntermTyped* base)
+// Return true if this is a geometry shader input array or tessellation control output array.
+bool TParseContext::isIoResizeArray(const TType& type)
 {
-    if (base->getType().getQualifier().storage == EvqVaryingIn) {
-        TIntermSymbol* symbol = base->getAsSymbolNode();
-        assert(symbol);
-        inputArrayNodeResizeList.push_back(symbol);
-        if (symbol && builtInName(symbol->getName())) {
-            // make sure we have a user-modifiable copy of this built-in input array
-            TSymbol* input = symbolTable.find(symbol->getName());
-            if (input->isReadOnly()) {
-                input = symbolTable.copyUp(input);
-                inputArraySymbolResizeList.push_back(input);
+    return type.isArray() &&
+           ((language == EShLangGeometry    && type.getQualifier().storage == EvqVaryingIn) ||
+            (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch));
+}
 
-                // Save it in the AST for linker use.
-                intermediate.addSymbolLinkageNode(linkage, *input);
+// Handle a dereference of a geometry shader input array or tessellation control output array.
+// See ioArrayNodeResizeList comment in ParseHelper.h.
+//
+void TParseContext::handleIoResizeArrayAccess(TSourceLoc loc, TIntermTyped* base)
+{
+    TIntermSymbol* symbol = base->getAsSymbolNode();
+    assert(symbol);
+    ioArrayNodeResizeList.push_back(symbol);
+    if (symbol && builtInName(symbol->getName())) {
+        // make sure we have a user-modifiable copy of this built-in input array
+        TSymbol* arry = symbolTable.find(symbol->getName());
+        if (arry->isReadOnly()) {
+            arry = symbolTable.copyUp(arry);
+
+            // fix array size, if already implicitly size
+            if (arry->getType().getArraySize() == 0) {
+                int newSize = getIoArrayImplicitSize();
+                if (newSize) {
+                    arry->getWritableType().changeArraySize(newSize);
+                    symbol->getWritableType().changeArraySize(newSize);
+                }
             }
+
+            ioArraySymbolResizeList.push_back(arry);
+
+            // Save it in the AST for linker use.
+            intermediate.addSymbolLinkageNode(linkage, *arry);
         }
     }
 }
 
-// If there has been an input primitive declaration, make sure all input array types
+// If there has been an input primitive declaration (geometry shader) or an output
+// number of vertices declaration(tessellation shader), make sure all input array types
 // match it in size.  Types come either from nodes in the AST or symbols in the 
 // symbol table.
 //
 // Types without an array size will be given one.
 // Types already having a size that is wrong will get an error.
 //
-void TParseContext::checkInputArrayConsistency(TSourceLoc loc, bool tailOnly)
+void TParseContext::checkIoArraysConsistency(TSourceLoc loc, bool tailOnly)
 {
-    TLayoutGeometry primitive = intermediate.getInputPrimitive();
-    if (primitive == ElgNone)
+    int requiredSize = getIoArrayImplicitSize();
+    if (requiredSize == 0)
         return;
 
+    const char* feature;
+    if (language == EShLangGeometry)
+        feature = TQualifier::getGeometryString(intermediate.getInputPrimitive());
+    else if (language == EShLangTessControl)
+        feature = "vertices";
+
     if (tailOnly) {
-        checkInputArrayConsistency(loc, primitive, inputArraySymbolResizeList.back()->getWritableType(), inputArraySymbolResizeList.back()->getName());
+        checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName());
         return;
     }
 
-    for (size_t i = 0; i < inputArrayNodeResizeList.size(); ++i)
-        checkInputArrayConsistency(loc, primitive, inputArrayNodeResizeList[i]->getWritableType(), inputArrayNodeResizeList[i]->getName());
+    for (size_t i = 0; i < ioArrayNodeResizeList.size(); ++i)
+        checkIoArrayConsistency(loc, requiredSize, feature, ioArrayNodeResizeList[i]->getWritableType(), ioArrayNodeResizeList[i]->getName());
 
-    for (size_t i = 0; i < inputArraySymbolResizeList.size(); ++i)
-        checkInputArrayConsistency(loc, primitive, inputArraySymbolResizeList[i]->getWritableType(), inputArraySymbolResizeList[i]->getName());
+    for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i)
+        checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName());
 }
 
-void TParseContext::checkInputArrayConsistency(TSourceLoc loc, TLayoutGeometry primitive, TType& type, const TString& name)
+int TParseContext::getIoArrayImplicitSize() const
 {
-    int requiredSize = TQualifier::mapGeometryToSize(primitive);
+    if (language == EShLangGeometry)
+        return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive());
+    else if (language == EShLangTessControl)
+        return intermediate.getVertices();
+    else
+        return 0;
+}
 
+void TParseContext::checkIoArrayConsistency(TSourceLoc loc, int requiredSize, const char* feature, TType& type, const TString& name)
+{
     if (type.getArraySize() == 0)
         type.changeArraySize(requiredSize);
-    else if (type.getArraySize() != requiredSize)
-        error(loc, "inconsistent input primitive for array size", TQualifier::getGeometryString(primitive), name.c_str());
+    else if (type.getArraySize() != requiredSize) {
+        if (language == EShLangGeometry)
+            error(loc, "inconsistent input primitive for array size", feature, name.c_str());
+        else if (language == EShLangTessControl)
+            error(loc, "inconsistent output number of vertices for array size", feature, name.c_str());
+        else
+            assert(0);
+    }
 }
 
 //
@@ -837,13 +879,31 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
     if (op == EOpArrayLength) {
         if (fnCall->getParamCount() > 0)
             error(loc, "method does not accept any arguments", fnCall->getName().c_str(), "");
-        int length;
-        if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray() || intermNode->getAsTyped()->getType().getArraySize() == 0) {
-            error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
-            length = 1;
+        int length = 0;
+        if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray())
+            error(loc, "", fnCall->getName().c_str(), "can only be applied to an array");
+        else if (intermNode->getAsTyped()->getType().getArraySize() == 0) {
+            bool implicitlySized = false;
+            if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType())) {
+                // We could be between a layout declaration that gives a built-in io array implicit size and 
+                // a user redeclaration of that array, meaning we have to substitute its implicit size here 
+                // without actually redeclaring the array.  (It is an error to use a member before the
+                // redeclaration, but not an error to use the array name itself.)
+                const TString& name = intermNode->getAsSymbolNode()->getName();
+                if (name == "gl_in" || name == "gl_out")
+                    length = getIoArrayImplicitSize();
+            }
+            if (length == 0) {
+                if (isIoResizeArray(intermNode->getAsTyped()->getType()))
+                    error(loc, "", fnCall->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
+                else
+                    error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
+            }
         } else
             length = intermNode->getAsTyped()->getType().getArraySize();
 
+        if (length == 0)
+            length = 1;
         TConstUnionArray unionArray(1);
         unionArray[0].setIConst(length);
         result = intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc);
@@ -1986,10 +2046,9 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
             symbolTable.insert(*symbol);
             newDeclaration = true;
 
-            // Handle user geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
-            if (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn && ! symbolTable.atBuiltInLevel()) {
-                inputArraySymbolResizeList.push_back(symbol);
-                checkInputArrayConsistency(loc, true);
+            if (! symbolTable.atBuiltInLevel() && isIoResizeArray(type)) {
+                ioArraySymbolResizeList.push_back(symbol);
+                checkIoArraysConsistency(loc, true);
             }
 
             return;
@@ -2016,8 +2075,8 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
         return;
     }
     if (newType.getArraySize() > 0) {
-        // be more leniant for input arrays to geometry shaders, where the redeclaration is the same size
-        if (! (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn && newType.getArraySize() == type.getArraySize()))
+        // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
+        if (! (isIoResizeArray(type) && newType.getArraySize() == type.getArraySize()))
             error(loc, "redeclaration of array with size", identifier.c_str(), "");
         return;
     }
@@ -2031,8 +2090,8 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
 
     newType.shareArraySizes(type);
 
-    if (language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn)
-        checkInputArrayConsistency(loc);
+    if (isIoResizeArray(type))
+        checkIoArraysConsistency(loc);
 }
 
 void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int index)
@@ -2064,9 +2123,8 @@ void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int in
     if (symbol->isReadOnly()) {
         symbol = symbolTable.copyUp(symbol);
         
-        // Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
-        if (language == EShLangGeometry && symbol->getType().getQualifier().storage == EvqVaryingIn)
-            inputArraySymbolResizeList.push_back(symbol);
+        if (isIoResizeArray(symbol->getType()))
+            ioArraySymbolResizeList.push_back(symbol);
 
         // Save it in the AST for linker use.
         intermediate.addSymbolLinkageNode(linkage, *symbol);
@@ -2128,16 +2186,15 @@ TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString&
             return 0;
 
         // If it wasn't at a built-in level, then it's already been redeclared;
-        // that is, this is a redeclaration of a redeclaration, reuse that initial
+        // that is, this is a redeclaration of a redeclaration; reuse that initial
         // redeclaration.  Otherwise, make the new one.
         if (builtIn) {
             // Copy the symbol up to make a writable version
             newDeclaration = true;
             symbol = symbolTable.copyUp(symbol);
 
-            // Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
-            if (language == EShLangGeometry && symbol->getType().getQualifier().storage == EvqVaryingIn && symbol->getType().isArray())
-                inputArraySymbolResizeList.push_back(symbol);
+            if (isIoResizeArray(symbol->getType()))
+                ioArraySymbolResizeList.push_back(symbol);
 
             // Save it in the AST for linker use.
             intermediate.addSymbolLinkageNode(linkage, *symbol);
@@ -2248,10 +2305,6 @@ void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList
         return;
     }
 
-    // Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
-    if (language == EShLangGeometry && block->getType().isArray() && block->getType().getQualifier().storage == EvqVaryingIn)
-        inputArraySymbolResizeList.push_back(block);
-
     // Edit and error check the container against the redeclaration
     //  - remove unused members
     //  - ensure remaining qualifiers/types match
@@ -2320,12 +2373,20 @@ void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList
         error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), "");
     else if (type.isArray() && type.getArraySize() > 0 && type.getArraySize() != arraySizes->getSize())
         error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
+    else if (type.isArray() && type.getArraySize() == 0 && arraySizes->getSize() > 0)
+        type.changeArraySize(arraySizes->getSize());
 
     symbolTable.insert(*block);
 
     // Check for general layout qualifier errors
     layoutTypeCheck(loc, *block);
 
+    // Tracking for implicit sizing of array
+    if (isIoResizeArray(block->getType())) {
+        ioArraySymbolResizeList.push_back(block);
+        checkIoArraysConsistency(loc, true);
+    }
+
     // Save it in the AST for linker use.
     intermediate.addSymbolLinkageNode(linkage, *block);
 }
@@ -2728,8 +2789,6 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
 
     case EShLangTessControl:
         if (id == "vertices") {
-            // TODO: tessellation: implement gl_out[] array sizing based on this
-            // TODO: tessellation: semantic check this is on the out qualifier only
             publicType.shaderQualifiers.vertices = value;
             return;
         }
@@ -2932,8 +2991,14 @@ void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TShaderQualifiers
         error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), "");
     if (shaderQualifiers.invocations > 0)
         error(loc, message, "invocations", "");
-    if (shaderQualifiers.vertices > 0)
-        error(loc, message, "max_vertices", "");
+    if (shaderQualifiers.vertices > 0) {
+        if (language == EShLangGeometry)
+            error(loc, message, "max_vertices", "");
+        else if (language == EShLangTessControl)
+            error(loc, message, "vertices", "");
+        else
+            assert(0);
+    }
 }
 
 //
@@ -3726,8 +3791,15 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
         if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) {            
             if (language == EShLangGeometry)
                 error(loc, "cannot change previously set layout value", "max_vertices", "");
-            else
+            else if (language == EShLangTessControl)
                 error(loc, "cannot change previously set layout value", "vertices", "");
+            else
+                assert(0);
+        } else if (language == EShLangTessControl) {
+            if (publicType.qualifier.storage != EvqVaryingOut)
+                error(loc, "can only apply to 'out'", "vertices", "");
+            else
+                checkIoArraysConsistency(loc);
         }
     }
     if (publicType.shaderQualifiers.invocations) {
@@ -3744,9 +3816,10 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
             case ElgTrianglesAdjacency:
             case ElgQuads:
             case ElgIsolines:
-                if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry))
-                    checkInputArrayConsistency(loc);
-                else
+                if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) {
+                    if (language == EShLangGeometry)
+                        checkIoArraysConsistency(loc);
+                } else
                     error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
                 break;
             default:
@@ -3761,7 +3834,7 @@ void TParseContext::updateStandaloneQualifierDefaults(TSourceLoc loc, const TPub
                     error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
                 break;
             default:
-                error(loc, "does not only apply to output", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
+                error(loc, "does not apply to output", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
             }
         } else
             error(loc, "cannot be used here", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), "");
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 541447012c90322c7845e97a50e0975524207bc8..3d4713b049d30fb0487ee0ced10c66f52a37599d 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -84,9 +84,13 @@ public:
     TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
     void checkIndex(TSourceLoc, const TType&, int& index);
     void handleIndexLimits(TSourceLoc, TIntermTyped* base, TIntermTyped* index);
-    void handleInputArrayAccess(TSourceLoc, TIntermTyped* base);
-    void checkInputArrayConsistency(TSourceLoc, bool tailOnly = false);
-    void checkInputArrayConsistency(TSourceLoc, TLayoutGeometry, TType&, const TString&);
+
+    bool isIoResizeArray(const TType&);
+    void handleIoResizeArrayAccess(TSourceLoc, TIntermTyped* base);
+    void checkIoArraysConsistency(TSourceLoc, bool tailOnly = false);
+    int getIoArrayImplicitSize() const;
+    void checkIoArrayConsistency(TSourceLoc, int requiredSize, const char* feature, TType&, const TString&);
+
     TIntermTyped* handleDotDereference(TSourceLoc, TIntermTyped* base, TString& field);
     TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
@@ -257,6 +261,11 @@ protected:
     //
     // Geometry shader input arrays:
     //  - array sizing is based on input primitive and/or explicit size
+    //
+    // Tessellation control output arrays:
+    //  - array sizing is based on output layout(vertices=...) and/or explicit size
+    //
+    // Both:
     //  - array sizing is retroactive
     //  - built-in block redeclarations interact with this
     //
@@ -270,23 +279,23 @@ protected:
     //  - the resize-list starts empty at beginning of user-shader compilation, it does
     //    not have built-ins in it
     //
-    //  - on built-in input array use: copy-up symbol and add both the symbol and
+    //  - on built-in array use: copy-up symbol and add both the symbol and
     //    its use to resize-list
     //
-    //  - on user-input array declaration: add it to the resize-list
+    //  - on user array declaration: add it to the resize-list
     //
     //  - on block redeclaration: copy-up symbol and add it to the resize-list
     //     * note, that appropriately gives an error if redeclaring a block that
     //       was already used and hence already copied-up
     //
-    //  - on seeing an input primitive-layout declaration, fix everything in the resize-list,
-    //    giving errors for mismatch
+    //  - on seeing a layout declaration that sizes the array, fix everything in the 
+    //    resize-list, giving errors for mismatch
     //
     //  - on seeing an array size declaration, give errors on mismatch between it and previous
-    //    input primitive declarations
+    //    array-sizing declarations
     //
-    TVector<TIntermSymbol*> inputArrayNodeResizeList;
-    TVector<TSymbol*> inputArraySymbolResizeList;
+    TVector<TIntermSymbol*> ioArrayNodeResizeList;
+    TVector<TSymbol*> ioArraySymbolResizeList;
 };
 
 } // end namespace glslang
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 74394c506a905173d54b4393fae3bf490c86f416..802bb2499536b063c5923d90082f1bab7e1e0752 100644
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -88,8 +88,14 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
     
     if (vertices == 0)
         vertices = unit.vertices;
-    else if (vertices != unit.vertices)
-        error(infoSink, "Contradictory layout max_vertices values");
+    else if (vertices != unit.vertices) {
+        if (language == EShLangGeometry)
+            error(infoSink, "Contradictory layout max_vertices values");
+        else if (language == EShLangTessControl)
+            error(infoSink, "Contradictory layout vertices values");
+        else
+            assert(0);
+    }
 
     if (vertexSpacing == EvsNone)
         vertexSpacing = unit.vertexSpacing;
@@ -297,11 +303,14 @@ void TIntermediate::finalCheck(TInfoSink& infoSink)
 
     switch (language) {
     case EShLangVertex:
+        break;
     case EShLangTessControl:
+        if (vertices == 0)
+            error(infoSink, "At least one shader must specify an output layout(vertices=...)");
         break;
     case EShLangTessEvaluation:
         if (inputPrimitive == ElgNone)
-            error(infoSink, "At least one tessellation shader must specify an input layout primitive");
+            error(infoSink, "At least one shader must specify an input layout primitive");
         if (vertexSpacing == EvsNone)
             vertexSpacing = EvsEqual;
         if (vertexOrder == EvoNone)
@@ -309,13 +318,14 @@ void TIntermediate::finalCheck(TInfoSink& infoSink)
         break;
     case EShLangGeometry:
         if (inputPrimitive == ElgNone)
-            error(infoSink, "At least one geometry shader must specify an input layout primitive");
+            error(infoSink, "At least one shader must specify an input layout primitive");
         if (outputPrimitive == ElgNone)
-            error(infoSink, "At least one geometry shader must specify an output layout primitive");
+            error(infoSink, "At least one shader must specify an output layout primitive");
         if (vertices == 0)
-            error(infoSink, "At least one geometry shader must specify a layout(max_vertices = value)");
+            error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
         break;
     case EShLangFragment:
+        break;
     case EShLangCompute:
         break;
     }
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index b9b51c39d87fc4b1ff5342776500e2683f7a435d..539a94722fdec66ea3b91e1e7ed599258583b215 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -129,6 +129,7 @@ public:
         vertices = m;
         return true;
     }
+    int getVertices() const { return vertices; }
     bool setInputPrimitive(TLayoutGeometry p)
     {
         if (inputPrimitive != ElgNone)