diff --git a/Test/300.vert b/Test/300.vert
index 11a0078565e2a54728e97125fe3330770579d16e..5abf450846aed75f54c9731948b009384d8ded84 100644
--- a/Test/300.vert
+++ b/Test/300.vert
@@ -168,3 +168,7 @@ int Bfoo;
 layout(std140) Binst;    // ERROR
 layout(std140) Bblock;   // ERROR
 layout(std140) Bfoo;     // ERROR
+
+struct SNA {
+    int a[];             // ERROR
+};
diff --git a/Test/310.comp b/Test/310.comp
new file mode 100644
index 0000000000000000000000000000000000000000..2f172feb86695d3f3787925c504a24d796df121d
--- /dev/null
+++ b/Test/310.comp
@@ -0,0 +1,141 @@
+#version 310 es
+
+layout(local_size_x = 2) in;
+layout(local_size_x = 16) in;     // ERROR, changing
+layout(local_size_z = 4096) in;   // ERROR, too large
+layout(local_size_x = 2) in;
+
+const int total = gl_MaxComputeWorkGroupCount.y 
+                + gl_MaxComputeUniformComponents
+                + gl_MaxComputeTextureImageUnits
+                + gl_MaxComputeImageUniforms
+                + gl_MaxComputeAtomicCounters
+                + gl_MaxComputeAtomicCounterBuffers;
+
+buffer ShaderStorageBlock
+{
+    int value;
+    float values[];
+};
+
+buffer InvalidShaderStorageBlock
+{
+    float values[];  // ERROR
+    int value;
+} invalid;
+
+void main()
+{
+    barrier();
+    memoryBarrier();
+    memoryBarrierAtomicCounter();
+    memoryBarrierBuffer();
+    memoryBarrierShared();
+    memoryBarrierImage();
+    groupMemoryBarrier();
+    value = int(values[gl_LocalInvocationIndex]);
+}
+
+layout(location = 2) in vec3 v3;      // ERROR
+in float f;                           // ERROR
+out float fo;                         // ERROR
+
+shared vec4 s;
+layout(location = 2) shared vec4 sl;  // ERROR
+shared float fs = 4.2;                // ERROR
+
+layout(local_size_x = 2, local_size_y = 3, local_size_z = 4) out;  // ERROR
+
+int arrX[gl_WorkGroupSize.x];
+int arrY[gl_WorkGroupSize.y];
+int arrZ[gl_WorkGroupSize.z];
+
+readonly buffer roblock
+{
+    int value;
+    float values[];
+} ro;
+
+void foo()
+{
+    ro.values[2] = 4.7;        // ERROR, readonly
+    ro.values.length();
+    ++s;
+}
+
+buffer vec4 v;  // ERROR
+
+uniform usampler2D us2dbad;  // ERROR, default precision
+
+precision highp usampler2D;
+precision highp iimage2DArray;
+precision highp iimage2D;
+
+uniform usampler2D us2d;
+
+uniform iimage2DArray ii2dabad;  // ERROR, not writeonly
+uniform writeonly iimage2DArray ii2da;
+
+layout(r32i) uniform iimage2D iimg2D;
+layout(rgba32i) uniform iimage2D iimg2Drgba;
+layout(rgba32f) uniform image2D img2Drgba;
+layout(r32ui) uniform uimage2D uimg2D;
+
+void qux()
+{
+    int i = 4;
+    imageAtomicCompSwap(iimg2D, ivec2(i,i), i, i);// ERROR no longer in 310
+    imageAtomicAdd(uimg2D, ivec2(i,i), uint(i));  // ERROR no longer in 310
+    imageAtomicMin(iimg2Drgba, ivec2(i,i), i);    // ERROR no longer in 310  // ERROR iimg2Drgba does not have r32i layout
+    imageAtomicMax(img2Drgba, ivec2(i,i), i);     // ERROR no longer in 310  // ERROR img2Drgba is not integer image
+    ivec4 pos = imageLoad(iimg2D, ivec2(i,i));
+    imageStore(ii2da, ivec3(i,i,i), ivec4(0));
+    imageLoad(img2Drgba, ivec2(i,i));
+    imageLoad(ii2da, ivec3(i,i,i));       // ERROR, drops writeonly
+}
+
+volatile float vol; // ERROR, not an image
+readonly int vol2;  // ERROR, not an image
+
+void passr(coherent readonly iimage2D image)
+{
+}
+
+layout(r32i) coherent readonly uniform iimage2D qualim1;
+layout(r32i) coherent restrict readonly uniform iimage2D qualim2;
+
+void passrc()
+{
+    passr(qualim1);
+    passr(qualim2);   // ERROR, drops restrict
+    passr(iimg2D);
+}
+
+layout(rg8i) uniform uimage2D i1bad;     // ERROR, type mismatch
+layout(rgba32i) uniform image2D i2bad;   // ERROR, type mismatch
+layout(rgba32f) uniform uimage2D i3bad;  // ERROR, type mismatch
+layout(r8_snorm) uniform iimage2D i4bad; // ERROR, type mismatch
+layout(rgba32ui) uniform iimage2D i5bad; // ERROR, type mismatch
+layout(r8ui) uniform iimage2D i6bad;     // ERROR, type mismatch
+
+layout(binding = 0) uniform atomic_uint counter;
+
+uint func(atomic_uint c)
+{
+    return atomicCounterIncrement(c);
+}
+
+uint func2(out atomic_uint c) // ERROR, output
+{
+    return counter;           // ERROR, type mismatch
+    return atomicCounter(counter);
+}
+
+void mainAC()
+{
+     atomic_uint non_uniform_counter; // ERROR
+     uint val = atomicCounter(counter);
+     atomicCounterDecrement(counter);
+}
+
+layout(binding = 1) uniform mediump atomic_uint counterBad;  // ERROR, not highp
diff --git a/Test/310.frag b/Test/310.frag
new file mode 100644
index 0000000000000000000000000000000000000000..7399159ef08feb2ed539605269d0c25dae424aba
--- /dev/null
+++ b/Test/310.frag
@@ -0,0 +1,46 @@
+#version 310 es
+
+precision mediump float;
+precision highp usampler2D;
+precision highp sampler2D;
+precision highp isampler2DArray;
+
+layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord;  // ERROR, not supported
+
+layout(location = 2) in vec3 v3;
+layout(location = 2) in mat4 yi;  // ERROR, locations conflict with xi
+
+uniform sampler2D arrayedSampler[5];
+uniform usampler2D usamp2d;
+uniform usampler2DRect samp2dr;      // ERROR, reserved
+uniform isampler2DArray isamp2DA;
+
+in vec2 c2D;
+uniform int i;
+
+void main()
+{
+    vec4 v = texture(arrayedSampler[i], c2D);  // ERROR
+
+    ivec2 offsets[4];
+    const ivec2 constOffsets[4] = ivec2[4](ivec2(1,2), ivec2(3,4), ivec2(15,16), ivec2(-2,0));
+    uvec4 uv4 = textureGatherOffsets(samp2dr, c2D, offsets, 2);  // ERROR, not supported
+    vec4 v4 = textureGather(arrayedSampler[0], c2D);
+    ivec4 iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 3);
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), i);  // ERROR, last argument not const
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 4);  // ERROR, last argument out of range
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(1), 1+2);
+    iv4 = textureGatherOffset(isamp2DA, vec3(0.1), ivec2(i));
+}
+
+out vec4 outp;
+
+void foo23()
+{
+    const ivec2[3] offsets = ivec2[3](ivec2(1,2), ivec2(3,4), ivec2(15,16));
+
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), ivec2(c2D));     // ERROR, offset not constant
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), offsets[1]);
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), offsets[2]);     // ERROR, offset out of range
+    textureProjGradOffset(usamp2d, outp, vec2(0.0), vec2(0.0), ivec2(-10, 20)); // ERROR, offset out of range
+}
diff --git a/Test/310.vert b/Test/310.vert
new file mode 100644
index 0000000000000000000000000000000000000000..8f0dee495ea882982e92e8121d8752c3cf5722ee
--- /dev/null
+++ b/Test/310.vert
@@ -0,0 +1,10 @@
+#version 310 es
+
+shared vec4 s;   // ERROR
+layout(local_size_x = 2) out;  // ERROR
+buffer vec4 v;  // ERROR
+
+layout(location = 2) uniform mat4 x;
+layout(location = 3) uniform mat4 y;
+layout(location = 2) out mat4 xi;
+layout(location = 3) out mat4 yi;  // ERROR, locations conflict with xi
diff --git a/Test/430.vert b/Test/430.vert
index 4cc8d29ee7344d63ab74be3cd98fdb8e6905879c..d1d31f4498c243670bad9253785e49531c87d6e0 100644
--- a/Test/430.vert
+++ b/Test/430.vert
@@ -143,7 +143,7 @@ out bblck5 {
     layout(xfb_stride=80, xfb_buffer=1, xfb_offset=64) vec4 bbv2;
 } bbinst5;
 
-shared vec4 sharedv;
+shared vec4 sharedv;                // ERROR
 
 void fooBarrier()
 {
diff --git a/Test/atomic_uint.frag b/Test/atomic_uint.frag
index 972cf28287350bafd34d05c5c4729f3e9d41fb75..a8371503c2e0e783f1a92fe04a1d9bea0c3713d5 100644
--- a/Test/atomic_uint.frag
+++ b/Test/atomic_uint.frag
@@ -9,7 +9,8 @@ uint func(atomic_uint c)
 
 uint func2(out atomic_uint c) // ERROR
 {
-    return counter;
+    return counter;           // ERROR, type mismatch
+    return atomicCounter(counter);
 }
 
 void main()
diff --git a/Test/baseResults/300.frag.out b/Test/baseResults/300.frag.out
index e0fda14f15b192663350a8539b57e06495431747..43fbe097113e5993581572cda359bbb04109eb43 100644
--- a/Test/baseResults/300.frag.out
+++ b/Test/baseResults/300.frag.out
@@ -19,11 +19,11 @@ ERROR: 0:85: 'dvec3' : Reserved word.
 ERROR: 0:85: 'double vector' : not supported with this profile: es
 ERROR: 0:86: 'dvec4' : Reserved word. 
 ERROR: 0:86: 'double vector' : not supported with this profile: es
-ERROR: 0:101: 'arrays of arrays' : not supported with this profile: es
-ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es
-ERROR: 0:102: 'arrays of arrays' : not supported with this profile: es
-ERROR: 0:103: 'arrays of arrays' : not supported with this profile: es
-ERROR: 0:100: 'arrays of arrays' : not supported with this profile: es
+ERROR: 0:101: 'arrays of arrays' : not supported for this version or the enabled extensions 
+ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions 
+ERROR: 0:102: 'arrays of arrays' : not supported for this version or the enabled extensions 
+ERROR: 0:103: 'arrays of arrays' : not supported for this version or the enabled extensions 
+ERROR: 0:100: 'arrays of arrays' : not supported for this version or the enabled extensions 
 ERROR: 0:111: 'variable indexing fragment shader ouput array' : not supported with this profile: es
 ERROR: 0:119: '==' : can't use with samplers or structs containing samplers 
 ERROR: 0:120: '!=' : can't use with samplers or structs containing samplers 
diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out
index d9d8c2fbe57baf0397041fbbae3c927c9adbe105..87f630e9eaf96c9eb680717f694bd96801364e2c 100644
--- a/Test/baseResults/300.vert.out
+++ b/Test/baseResults/300.vert.out
@@ -16,8 +16,8 @@ ERROR: 0:18: 'uniform' : too many storage qualifiers
 ERROR: 0:56: '#error' : GL_ES is set  
 ERROR: 0:62: '' : array size required 
 ERROR: 0:63: '' : array size required 
-ERROR: 0:65: '' : array size required 
 ERROR: 0:64: '' : array size required 
+ERROR: 0:65: 'implicitly-sized array in a block' : not supported with this profile: es
 ERROR: 0:67: '' : array size required 
 ERROR: 0:76: 'invariant' : cannot change qualification after use 
 ERROR: 0:78: 'invariant' : can only apply to an output: invIn
@@ -38,7 +38,8 @@ ERROR: 0:149: 'float' : cannot apply precision statement to this type; use 'floa
 ERROR: 0:168: 'Binst' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable 
 ERROR: 0:169: 'Bblock' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable 
 ERROR: 0:170: 'Bfoo' : cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable 
-ERROR: 39 compilation errors.  No code generated.
+ERROR: 0:173: '' : array size required 
+ERROR: 40 compilation errors.  No code generated.
 
 
 Shader version: 300
diff --git a/Test/baseResults/300layout.frag.out b/Test/baseResults/300layout.frag.out
index a7a7da897a7fc62575d910b56b402e54224b081d..21f12dd84a3b3f14ed05dc09c6d4dc28d038e078 100644
--- a/Test/baseResults/300layout.frag.out
+++ b/Test/baseResults/300layout.frag.out
@@ -1,8 +1,9 @@
 300layout.frag
 ERROR: 0:4: 'location qualifier on input' : not supported in this stage: fragment
+ERROR: 0:4: 'location qualifier on input' : not supported for this version or the enabled extensions 
 ERROR: 0:18: 'location' : overlapping use of location 41
 ERROR: 0:19: 'location' : overlapping use of location 40
-ERROR: 3 compilation errors.  No code generated.
+ERROR: 4 compilation errors.  No code generated.
 
 
 Shader version: 300
diff --git a/Test/baseResults/300layout.vert.out b/Test/baseResults/300layout.vert.out
index b5b1e26294fd8e5bdf8f640a107d1f71cbf429aa..f64db3bdc24cb7ab159afd716a63eca4237c0bcc 100644
--- a/Test/baseResults/300layout.vert.out
+++ b/Test/baseResults/300layout.vert.out
@@ -13,11 +13,12 @@ ERROR: 0:23: 'bad3' : member of block cannot have a packing layout qualifier
 ERROR: 0:31: 'T3' : nameless block contains a member that already has a name at global scope 
 ERROR: 0:38: 'output block' : not supported with this profile: es
 ERROR: 0:42: 'location qualifier on output' : not supported in this stage: vertex
-ERROR: 0:50: 'shared' : not supported with this profile: es
+ERROR: 0:42: 'location qualifier on output' : not supported for this version or the enabled extensions 
+ERROR: 0:50: 'shared' : not supported for this version or the enabled extensions 
 ERROR: 0:50: 'shared' : not supported in this stage: vertex
 ERROR: 0:54: 'layout' : cannot specify packing on a variable declaration 
 ERROR: 0:57: 'location' : overlapping use of location 40
-ERROR: 18 compilation errors.  No code generated.
+ERROR: 19 compilation errors.  No code generated.
 
 
 Shader version: 300
diff --git a/Test/baseResults/atomic_uint.frag.out b/Test/baseResults/atomic_uint.frag.out
index 246cf8b0131733a89417eb938736a158ded459f3..248df2e6a92d600a47b3aa9d4872bd134483e0a8 100644
--- a/Test/baseResults/atomic_uint.frag.out
+++ b/Test/baseResults/atomic_uint.frag.out
@@ -2,7 +2,7 @@ atomic_uint.frag
 Warning, version 420 is not yet complete; most version-specific features are present, but some are missing.
 ERROR: 0:10: 'atomic_uint' : samplers and atomic_uints cannot be output parameters 
 ERROR: 0:12: 'return' : type does not match, or is not convertible to, the function's return type 
-ERROR: 0:17: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter
+ERROR: 0:18: 'atomic_uint' : atomic_uints can only be used in uniform variables or function parameters: non_uniform_counter
 ERROR: 3 compilation errors.  No code generated.
 
 
@@ -21,16 +21,19 @@ ERROR: node is still EOpNull!
 0:12    Sequence
 0:12      Branch: Return with expression
 0:12        'counter' (layout(binding=0 ) uniform atomic_uint)
-0:15  Function Definition: main( (void)
-0:15    Function Parameters: 
+0:13      Branch: Return with expression
+0:13        Function Call: atomicCounter(au1; (uint)
+0:13          'counter' (layout(binding=0 ) uniform atomic_uint)
+0:16  Function Definition: main( (void)
+0:16    Function Parameters: 
 0:?     Sequence
-0:18      Sequence
-0:18        move second child to first child (uint)
-0:18          'val' (uint)
-0:18          Function Call: atomicCounter(au1; (uint)
-0:18            'counter' (layout(binding=0 ) uniform atomic_uint)
-0:19      Function Call: atomicCounterDecrement(au1; (uint)
-0:19        'counter' (layout(binding=0 ) uniform atomic_uint)
+0:19      Sequence
+0:19        move second child to first child (uint)
+0:19          'val' (uint)
+0:19          Function Call: atomicCounter(au1; (uint)
+0:19            'counter' (layout(binding=0 ) uniform atomic_uint)
+0:20      Function Call: atomicCounterDecrement(au1; (uint)
+0:20        'counter' (layout(binding=0 ) uniform atomic_uint)
 0:?   Linker Objects
 0:?     'counter' (layout(binding=0 ) uniform atomic_uint)
 
@@ -53,16 +56,19 @@ ERROR: node is still EOpNull!
 0:12    Sequence
 0:12      Branch: Return with expression
 0:12        'counter' (layout(binding=0 ) uniform atomic_uint)
-0:15  Function Definition: main( (void)
-0:15    Function Parameters: 
+0:13      Branch: Return with expression
+0:13        Function Call: atomicCounter(au1; (uint)
+0:13          'counter' (layout(binding=0 ) uniform atomic_uint)
+0:16  Function Definition: main( (void)
+0:16    Function Parameters: 
 0:?     Sequence
-0:18      Sequence
-0:18        move second child to first child (uint)
-0:18          'val' (uint)
-0:18          Function Call: atomicCounter(au1; (uint)
-0:18            'counter' (layout(binding=0 ) uniform atomic_uint)
-0:19      Function Call: atomicCounterDecrement(au1; (uint)
-0:19        'counter' (layout(binding=0 ) uniform atomic_uint)
+0:19      Sequence
+0:19        move second child to first child (uint)
+0:19          'val' (uint)
+0:19          Function Call: atomicCounter(au1; (uint)
+0:19            'counter' (layout(binding=0 ) uniform atomic_uint)
+0:20      Function Call: atomicCounterDecrement(au1; (uint)
+0:20        'counter' (layout(binding=0 ) uniform atomic_uint)
 0:?   Linker Objects
 0:?     'counter' (layout(binding=0 ) uniform atomic_uint)
 
diff --git a/Test/testlist b/Test/testlist
index 286c1fd0c2ebc1c0ad62b27501993dbdba241533..ba21ea1fcaef1ae16e5f104951a5abde57bed98a 100644
--- a/Test/testlist
+++ b/Test/testlist
@@ -36,6 +36,9 @@ comment.frag
 300layout.frag
 300operations.frag
 300block.frag
+310.comp
+310.vert
+310.frag
 330.frag
 330comp.frag
 constErrors.frag
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index bc89e1fb243dd2905824954c32a6766ccc11a465..40c6b45c5694cd98fef5979c232174cb21138d12 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -248,20 +248,23 @@ enum TLayoutFormat {
     // Float image
     ElfRgba32f,
     ElfRgba16f,
+    ElfR32f,
+    ElfRgba8,
+    ElfRgba8Snorm,
+
+    ElfEsFloatGuard,    // to help with comparisons
+
     ElfRg32f,
     ElfRg16f,
     ElfR11fG11fB10f,
-    ElfR32f,
     ElfR16f,
     ElfRgba16,
     ElfRgb10A2,
-    ElfRgba8,
     ElfRg16,
     ElfRg8,
     ElfR16,
     ElfR8,
     ElfRgba16Snorm,
-    ElfRgba8Snorm,
     ElfRg16Snorm,
     ElfRg8Snorm,
     ElfR16Snorm,
@@ -273,10 +276,13 @@ enum TLayoutFormat {
     ElfRgba32i,
     ElfRgba16i,
     ElfRgba8i,
+    ElfR32i,
+
+    ElfEsIntGuard,     // to help with comparisons
+
     ElfRg32i,
     ElfRg16i,
     ElfRg8i,
-    ElfR32i,
     ElfR16i,
     ElfR8i,
 
@@ -286,10 +292,13 @@ enum TLayoutFormat {
     ElfRgba32ui,
     ElfRgba16ui,
     ElfRgba8ui,
+    ElfR32ui,
+
+    ElfEsUintGuard,    // to help with comparisons
+
     ElfRg32ui,
     ElfRg16ui,
     ElfRg8ui,
-    ElfR32ui,
     ElfR16ui,
     ElfR8ui,
 
diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp
index 73466e7ccb4447179f89d4e320400d33995ce029..42e5c7f2507702957dff9014932c1058fd8955ed 100644
--- a/glslang/MachineIndependent/Initialize.cpp
+++ b/glslang/MachineIndependent/Initialize.cpp
@@ -743,7 +743,8 @@ void TBuiltIns::initialize(int version, EProfile profile)
     //
     // Atomic counter functions.
     //
-    if (profile != EEsProfile && version >= 420) {
+    if ((profile != EEsProfile && version >= 420) ||
+        (profile == EEsProfile && version >= 310)) {
         commonBuiltins.append(
             "uint atomicCounterIncrement(atomic_uint x);"
             "uint atomicCounterDecrement(atomic_uint x);"
@@ -841,38 +842,37 @@ void TBuiltIns::initialize(int version, EProfile profile)
             
             "\n");
     }
-    if (profile != EEsProfile) {
-        //============================================================================
-        //
-        // Prototypes for all control functions.
-        //
-        //============================================================================
-
-        if (version >= 150)
-            stageBuiltins[EShLangTessControl].append(
-                "void barrier();"
-                );
-        if (version >= 430)
-            stageBuiltins[EShLangCompute].append(
-                "void barrier();"
-                );
 
-        if (version >= 130)
-            commonBuiltins.append(
-                "void memoryBarrier();"
-                );
-        if (version >= 430) {
-            commonBuiltins.append(
-                "void memoryBarrierAtomicCounter();"
-                "void memoryBarrierBuffer();"
-                "void memoryBarrierImage();"
-                );
-            stageBuiltins[EShLangCompute].append(
-                "void memoryBarrierShared();"
-                "void groupMemoryBarrier();"
-                );
-        }
+    //============================================================================
+    //
+    // Prototypes for all control functions.
+    //
+    //============================================================================
+    bool esBarrier = (profile == EEsProfile && version >= 310);
+    if (profile != EEsProfile && version >= 150)
+        stageBuiltins[EShLangTessControl].append(
+            "void barrier();"
+            );
+    if ((profile != EEsProfile && version >= 430) || esBarrier)
+        stageBuiltins[EShLangCompute].append(
+            "void barrier();"
+            );
+    if ((profile != EEsProfile && version >= 130) || esBarrier)
+        commonBuiltins.append(
+            "void memoryBarrier();"
+            );
+    if ((profile != EEsProfile && version >= 430) || esBarrier) {
+        commonBuiltins.append(
+            "void memoryBarrierAtomicCounter();"
+            "void memoryBarrierBuffer();"
+            "void memoryBarrierImage();"
+            );
+        stageBuiltins[EShLangCompute].append(
+            "void memoryBarrierShared();"
+            "void groupMemoryBarrier();"
+            );
     }
+
     //============================================================================
     //
     // Prototypes for built-in functions seen by fragment shaders only.
@@ -1088,7 +1088,8 @@ void TBuiltIns::initialize(int version, EProfile profile)
     //
     //============================================================================
 
-    if (version >= 430) {
+    if (profile != EEsProfile && version >= 430 ||
+        profile == EEsProfile && version >= 310) {
         stageBuiltins[EShLangCompute].append(
             "in uvec3 gl_NumWorkGroups;"
             "const uvec3 gl_WorkGroupSize = uvec3(1,1,1);"
@@ -1276,11 +1277,11 @@ void TBuiltIns::initialize(int version, EProfile profile)
             "out vec4 gl_ClipVertex;"
             );
 
-        if (version >= 400)
+        if (version >= 400 && profile != EEsProfile)
             stageBuiltins[EShLangGeometry].append(
             "in int gl_InvocationID;"
             );
-        if (version >= 410)
+        if (version >= 410 && profile != EEsProfile)
             stageBuiltins[EShLangGeometry].append(
             "out int gl_ViewportIndex;"
             );
@@ -1434,6 +1435,11 @@ void TBuiltIns::initialize(int version, EProfile profile)
                 "flat in int gl_Layer;"
                 "flat in int gl_ViewportIndex;"
                 );
+
+        if (version >= 450)
+            stageBuiltins[EShLangFragment].append(
+                "bool gl_HelperInvocation;"     // needs qualifier fixed later
+                );
     } else {
         // ES profile
 
@@ -1444,13 +1450,18 @@ void TBuiltIns::initialize(int version, EProfile profile)
                 "mediump vec4 gl_FragColor;"    // needs qualifier fixed later
                 "mediump vec2 gl_PointCoord;"   // needs qualifier fixed later
                 );
-        else if (version == 300)
+        else if (version >= 300) {
             stageBuiltins[EShLangFragment].append(
                 "highp   vec4  gl_FragCoord;"    // needs qualifier fixed later
                 "        bool  gl_FrontFacing;"  // needs qualifier fixed later
                 "mediump vec2  gl_PointCoord;"   // needs qualifier fixed later
                 "highp   float gl_FragDepth;"    // needs qualifier fixed later
                 );
+            if (version >= 310)
+                stageBuiltins[EShLangFragment].append(
+                        "bool  gl_HelperInvocation;"  // needs qualifier fixed later
+                    );
+        }
         stageBuiltins[EShLangFragment].append(
             "highp float gl_FragDepthEXT;"       // GL_EXT_frag_depth
             );
@@ -1554,7 +1565,7 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi
     // textureSize
     //
 
-    if (version < 430 && sampler.image)
+    if (sampler.image && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 430)))
         return;
 
     if (profile == EEsProfile)
@@ -1607,40 +1618,42 @@ void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int versi
     commonBuiltins.append(prefixes[sampler.type]);
     commonBuiltins.append("vec4);\n");
 
-    if (sampler.type == EbtInt || sampler.type == EbtUint) {
-        const char* dataType = sampler.type == EbtInt ? "int" : "uint";
-
-        const int numBuiltins = 7;
-
-        static const char* atomicFunc[numBuiltins] = {
-            " imageAtomicAdd(",
-            " imageAtomicMin(",
-            " imageAtomicMax(",
-            " imageAtomicAnd(",
-            " imageAtomicOr(",
-            " imageAtomicXor(",
-            " imageAtomicExchange("
-        }; 
+    if (profile != EEsProfile) {
+        if (sampler.type == EbtInt || sampler.type == EbtUint) {
+            const char* dataType = sampler.type == EbtInt ? "int" : "uint";
+
+            const int numBuiltins = 7;
+
+            static const char* atomicFunc[numBuiltins] = {
+                " imageAtomicAdd(",
+                " imageAtomicMin(",
+                " imageAtomicMax(",
+                " imageAtomicAnd(",
+                " imageAtomicOr(",
+                " imageAtomicXor(",
+                " imageAtomicExchange("
+            }; 
+
+            for (size_t i = 0; i < numBuiltins; ++i) {
+                commonBuiltins.append(dataType);
+                commonBuiltins.append(atomicFunc[i]);
+                if (version >= 450)
+                    commonBuiltins.append("coherent ");
+                commonBuiltins.append(imageParams);
+                commonBuiltins.append(", ");
+                commonBuiltins.append(dataType);
+                commonBuiltins.append(");\n");
+            }
 
-        for (size_t i = 0; i < numBuiltins; ++i) {
             commonBuiltins.append(dataType);
-            commonBuiltins.append(atomicFunc[i]);
-            if (version >= 450)
-                commonBuiltins.append("coherent ");
+            commonBuiltins.append(" imageAtomicCompSwap(");
             commonBuiltins.append(imageParams);
             commonBuiltins.append(", ");
             commonBuiltins.append(dataType);
+            commonBuiltins.append(", ");
+            commonBuiltins.append(dataType);
             commonBuiltins.append(");\n");
         }
-
-        commonBuiltins.append(dataType);
-        commonBuiltins.append(" imageAtomicCompSwap(");
-        commonBuiltins.append(imageParams);
-        commonBuiltins.append(", ");
-        commonBuiltins.append(dataType);
-        commonBuiltins.append(", ");
-        commonBuiltins.append(dataType);
-        commonBuiltins.append(");\n");
     }
 }
 
@@ -1848,6 +1861,9 @@ void TBuiltIns::addGatherFunctions(TSampler sampler, TString& typeName, int vers
 
     for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name:  none, Offset, and Offsets
 
+        if (profile == EEsProfile && offset == 2)
+            continue;
+
         for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument
 
             if (comp > 0 && sampler.shadow)
@@ -2156,24 +2172,6 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
             s.append(builtInConstant);
         }
 
-        // atomic counters
-        if (version >= 420) {
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources.);
-            //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources.);
-        }
-
         // images
         if (version >= 130) {
             snprintf(builtInConstant, maxSize, "const int gl_MaxImageUnits = %d;", resources.maxImageUnits);
@@ -2198,29 +2196,6 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
             s.append(builtInConstant);
         }
 
-        // compute
-        if (version >= 430) {
-            snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = {%d,%d,%d};", resources.maxComputeWorkGroupCountX,
-                                                                                                        resources.maxComputeWorkGroupCountY,
-                                                                                                        resources.maxComputeWorkGroupCountZ);                
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = {%d,%d,%d};", resources.maxComputeWorkGroupSizeX,
-                                                                                                        resources.maxComputeWorkGroupSizeY,
-                                                                                                        resources.maxComputeWorkGroupSizeZ);
-            s.append(builtInConstant);
-
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters);
-            s.append(builtInConstant);
-            snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers);
-            s.append(builtInConstant);
-        }
-
         // enhanced layouts
         if (version >= 430) {
             snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackBuffers = %d;", resources.maxTransformFeedbackBuffers);
@@ -2230,6 +2205,50 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
         }
     }
 
+    // TODO: atomic counters 
+    if (profile == EEsProfile && version >= 310 || profile != EEsProfile && version >= 420) {
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources.);
+    }
+    if (profile != EEsProfile && version >= 420) {
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.);
+        //snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.);
+    }
+
+
+    // compute
+    if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 430)) {
+        snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupCountX,
+                                                                                                    resources.maxComputeWorkGroupCountY,
+                                                                                                    resources.maxComputeWorkGroupCountZ);                
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupSizeX,
+                                                                                                    resources.maxComputeWorkGroupSizeY,
+                                                                                                    resources.maxComputeWorkGroupSizeZ);
+        s.append(builtInConstant);
+
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters);
+        s.append(builtInConstant);
+        snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers);
+        s.append(builtInConstant);
+    }
+
     s.append("\n");
 }
 
@@ -2284,12 +2303,13 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
         break;
 
     case EShLangFragment:
-        SpecialQualifier("gl_FrontFacing",  EvqFace, symbolTable);
-        SpecialQualifier("gl_FragCoord",    EvqFragCoord, symbolTable);
-        SpecialQualifier("gl_PointCoord",   EvqPointCoord, symbolTable);
-        SpecialQualifier("gl_FragColor",    EvqFragColor, symbolTable);
-        SpecialQualifier("gl_FragDepth",    EvqFragDepth, symbolTable);
-        SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, symbolTable);
+        SpecialQualifier("gl_FrontFacing",      EvqFace, symbolTable);
+        SpecialQualifier("gl_FragCoord",        EvqFragCoord, symbolTable);
+        SpecialQualifier("gl_PointCoord",       EvqPointCoord, symbolTable);
+        SpecialQualifier("gl_FragColor",        EvqFragColor, symbolTable);
+        SpecialQualifier("gl_FragDepth",        EvqFragDepth, symbolTable);
+        SpecialQualifier("gl_FragDepthEXT",     EvqFragDepth, symbolTable);
+        SpecialQualifier("gl_HelperInvocation", EvqIn, symbolTable);
         if (version == 100) {
             symbolTable.setFunctionExtensions("dFdx",   1, &GL_OES_standard_derivatives);
             symbolTable.setFunctionExtensions("dFdy",   1, &GL_OES_standard_derivatives);
@@ -2339,7 +2359,7 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
         }
 
         // GL_ARB_shader_image_load_store
-        if (version < 420)
+        if (profile != EEsProfile && version < 420)
             symbolTable.setFunctionExtensions("memoryBarrier", 1, &GL_ARB_shader_image_load_store);
         // All the image access functions are protected by checks on the type of the first argument.
 
@@ -2495,7 +2515,7 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
 //
 void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
 {
-    if (version >= 430 && version < 440) {
+    if (profile != EEsProfile && version >= 430 && version < 440) {
         symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &GL_ARB_enhanced_layouts);
         symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &GL_ARB_enhanced_layouts);
     }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index efc5d938c73b8f851d9f2190b73b767729ec1fac..df0f34a30fcd7ec1d561e56709b41b0f8294c1c9 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -82,15 +82,16 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb,
         case EShLangFragment:
             defaultPrecision[EbtInt] = EpqMedium;
             defaultPrecision[EbtUint] = EpqMedium;
-            defaultPrecision[EbtSampler] = EpqLow;
             break;
         default:
             defaultPrecision[EbtInt] = EpqHigh;
             defaultPrecision[EbtUint] = EpqHigh;
             defaultPrecision[EbtFloat] = EpqHigh;
-            defaultPrecision[EbtSampler] = EpqLow;
             break;
         }
+
+        defaultPrecision[EbtSampler] = EpqLow;
+        defaultPrecision[EbtAtomicUint] = EpqHigh;
     }
 
     globalUniformDefaults.clear();
@@ -1216,7 +1217,7 @@ void TParseContext::nonOpBuiltInCheck(TSourceLoc loc, const TFunction& fnCandida
         if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) {
             TString featureString = fnCandidate.getName() + "(...)";
             const char* feature = featureString.c_str();
-            requireProfile(loc, ~EEsProfile, feature);
+            profileRequires(loc, EEsProfile, 310, 0, feature);
 
             int compArg = -1;  // track which argument, if any, is the constant component argument
             if (fnCandidate.getName().compare("textureGatherOffset") == 0) {
@@ -2067,7 +2068,9 @@ void TParseContext::mergeQualifiers(TSourceLoc loc, TQualifier& dst, const TQual
         error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective)", "", "");
 
     // Ordering
-    if (! force && version < 420 && ! extensionsTurnedOn(1, &GL_ARB_shading_language_420pack)) {
+    if (! force && ((profile != EEsProfile && version < 420) || 
+                     profile == EEsProfile && version < 310)
+                && ! extensionsTurnedOn(1, &GL_ARB_shading_language_420pack)) {
         // non-function parameters
         if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone))
             error(loc, "invariant qualifier must appear first", "", "");
@@ -2173,7 +2176,10 @@ void TParseContext::precisionQualifierCheck(TSourceLoc loc, TPublicType& publicT
     if (profile != EEsProfile || parsingBuiltins)
         return;
 
-    if (publicType.basicType == EbtFloat || publicType.basicType == EbtUint || publicType.basicType == EbtInt || publicType.basicType == EbtSampler) {
+    if (publicType.basicType == EbtAtomicUint && publicType.qualifier.precision != EpqNone && publicType.qualifier.precision != EpqHigh)
+        error(loc, "atomic counters can only be highp", "atomic_uint", "");
+
+    if (publicType.basicType == EbtFloat || publicType.basicType == EbtUint || publicType.basicType == EbtInt || publicType.basicType == EbtSampler || publicType.basicType == EbtAtomicUint) {
         if (publicType.qualifier.precision == EpqNone) {
             if (messages & EShMsgRelaxedErrors)
                 warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(publicType.basicType), "substituting 'mediump'");
@@ -2262,10 +2268,21 @@ void TParseContext::arraySizeRequiredCheck(TSourceLoc loc, int size)
     }
 }
 
+void TParseContext::structArrayCheck(TSourceLoc loc, TType* type)
+{
+    const TTypeList& structure = *type->getStruct();
+    for (int m = 0; m < (int)structure.size(); ++m) {
+        const TType& member = *structure[m].type;
+        if (member.isArray() && ! member.isExplicitlySizedArray())
+            arraySizeRequiredCheck(structure[m].loc, 0);
+    }
+}
+
 void TParseContext::arrayDimError(TSourceLoc loc)
 {
-    requireProfile(loc, ECoreProfile | ECompatibilityProfile, "arrays of arrays");
+    requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "arrays of arrays");
     profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "arrays of arrays");
+    profileRequires(loc, EEsProfile, 310, 0, "arrays of arrays");
 }
 
 void TParseContext::arrayDimCheck(TSourceLoc loc, TArraySizes* sizes1, TArraySizes* sizes2)
@@ -2955,15 +2972,20 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
         return;
     }
     if (id == TQualifier::getLayoutPackingString(ElpStd430)) {
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, "std430");
+        requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430");
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "std430");
+        profileRequires(loc, EEsProfile, 310, 0, "std430");
         publicType.qualifier.layoutPacking = ElpStd430;
         return;
     }
     for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) {
         if (id == TQualifier::getLayoutFormatString(format)) {
-            requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load store");
+            if ((format > ElfEsFloatGuard && format < ElfFloatGuard) ||
+                (format > ElfEsIntGuard && format < ElfIntGuard) ||
+                (format > ElfEsUintGuard && format < ElfCount))
+                requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format");
             profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shader_image_load_store, "image load store");
+            profileRequires(loc, EEsProfile, 310, GL_ARB_shader_image_load_store, "image load store");
             publicType.qualifier.layoutFormat = format;
             return;
         }
@@ -3097,8 +3119,9 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
     
     if (id == "offset") {
         const char* feature = "uniform buffer-member offset";
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+        requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, feature);
+        profileRequires(loc, EEsProfile, 310, 0, feature);
         publicType.qualifier.layoutOffset = value;
         return;
     } else if (id == "align") {
@@ -3121,8 +3144,8 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
             publicType.qualifier.layoutLocation = value;
         return;
     } else if (id == "binding") {
-        requireProfile(loc, ~EEsProfile, "binding");
         profileRequires(loc, ~EEsProfile, 420, GL_ARB_shading_language_420pack, "binding");
+        profileRequires(loc, EEsProfile, 310, 0, "binding");
         if ((unsigned int)value >= TQualifier::layoutBindingEnd)
             error(loc, "binding is too large", id.c_str(), "");
         else
@@ -3460,35 +3483,44 @@ void TParseContext::layoutQualifierCheck(TSourceLoc loc, const TQualifier& quali
         case EvqVaryingIn:
         {
             const char* feature = "location qualifier on input";
-            if (profile == EEsProfile)
+            if (profile == EEsProfile && version < 310)
                 requireStage(loc, EShLangVertex, feature);
-            requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+            else
+                requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
             if (language == EShLangVertex) {
                 const char* exts[2] = { GL_ARB_separate_shader_objects, GL_ARB_explicit_attrib_location };
                 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
-            } else
+                profileRequires(loc, EEsProfile, 300, 0, feature);
+            } else {
                 profileRequires(loc, ~EEsProfile, 410, GL_ARB_separate_shader_objects, feature);
+                profileRequires(loc, EEsProfile, 310, 0, feature);
+            }
             break;
         }
         case EvqVaryingOut:
         {
             const char* feature = "location qualifier on output";
-            if (profile == EEsProfile)
+            if (profile == EEsProfile && version < 310)
                 requireStage(loc, EShLangFragment, feature);
-            requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
+            else
+                requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature);
             if (language == EShLangFragment) {
                 const char* exts[2] = { GL_ARB_separate_shader_objects, GL_ARB_explicit_attrib_location };
                 profileRequires(loc, ~EEsProfile, 330, 2, exts, feature);
-            } else
+                profileRequires(loc, EEsProfile, 300, 0, feature);
+            } else {
                 profileRequires(loc, ~EEsProfile, 410, GL_ARB_separate_shader_objects, feature);
+                profileRequires(loc, EEsProfile, 310, 0, feature);
+            }
             break;
         }
         case EvqUniform:
         case EvqBuffer:
         {
             const char* feature = "location qualifier on uniform or buffer";
-            requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
+            requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature);
             profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, feature);
+            profileRequires(loc, EEsProfile, 310, 0, feature);
             break;
         }
         default:
@@ -4155,8 +4187,9 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
         profileRequires(loc, ENoProfile, 140, 0, "uniform block");
         break;
     case EvqBuffer:
-        requireProfile(loc, ECoreProfile | ECompatibilityProfile, "buffer block");
+        requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block");
         profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, 0, "buffer block");
+        profileRequires(loc, EEsProfile, 310, 0, "buffer block");
         break;
     case EvqVaryingIn:
         requireProfile(loc, ~EEsProfile, "input block");
@@ -4186,6 +4219,8 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
             error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), "");
         if (memberType.isRuntimeSizedArray() && member < typeList.size() - 1)
             error(memberLoc, "only the last member of a buffer block can be run-time sized", memberType.getFieldName().c_str(), "");
+        if (memberType.isImplicitlySizedArray())
+            requireProfile(memberLoc, ~EEsProfile, "implicitly-sized array in a block");
 
         TBasicType basicType = memberType.getBasicType();
         if (basicType == EbtSampler)
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 2c36c2ea677b25677915f017c8b0baabebb76d1e..b129e60fed117d849aefce5711babb1d35f5d685 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -117,6 +117,7 @@ public:
     void arraySizeCheck(TSourceLoc, TIntermTyped* expr, int& size);
     bool arrayQualifierError(TSourceLoc, const TQualifier&);
     void arraySizeRequiredCheck(TSourceLoc, int size);
+    void structArrayCheck(TSourceLoc, TType* structure);
     void arrayDimError(TSourceLoc);
     void arrayDimCheck(TSourceLoc, TArraySizes* sizes1, TArraySizes* sizes2);
     void arrayDimCheck(TSourceLoc, const TType*, TArraySizes*);
diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp
index a7a72e278210148f3e3d3929550824a21ec34017..1a459ba8ac1a5b4810e987a625ec1613834d3842 100644
--- a/glslang/MachineIndependent/Scan.cpp
+++ b/glslang/MachineIndependent/Scan.cpp
@@ -668,18 +668,25 @@ int TScanContext::tokenizeIdentifier()
         return keyword;
 
     case BUFFER:
-        if (parseContext.version < 430)
+        if ((parseContext.profile == EEsProfile && parseContext.version < 310) || 
+            (parseContext.profile != EEsProfile && parseContext.version < 430))
             return identifierOrType();
         return keyword;
 
     case ATOMIC_UINT:
-        return es30ReservedFromGLSL(420);
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        else
+            return es30ReservedFromGLSL(420);
 
     case COHERENT:
     case RESTRICT:
     case READONLY:
     case WRITEONLY:
-        return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420);
+        if (parseContext.profile == EEsProfile && parseContext.version >= 310)
+            return keyword;
+        else
+            return es30ReservedFromGLSL(parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store) ? 130 : 420);
 
     case VOLATILE:
         if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.profile == EEsProfile || (parseContext.version < 420 && ! parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))))
@@ -743,28 +750,30 @@ int TScanContext::tokenizeIdentifier()
     case IMAGE1D:
     case IIMAGE1D:
     case UIMAGE1D:
+    case IMAGE1DARRAY:
+    case IIMAGE1DARRAY:
+    case UIMAGE1DARRAY:
+    case IMAGE2DRECT:
+    case IIMAGE2DRECT:
+    case UIMAGE2DRECT:
+    case IMAGEBUFFER:
+    case IIMAGEBUFFER:
+    case UIMAGEBUFFER:
+        return firstGenerationImage(false);
+
     case IMAGE2D:
     case IIMAGE2D:
     case UIMAGE2D:
     case IMAGE3D:
     case IIMAGE3D:
     case UIMAGE3D:
-    case IMAGE2DRECT:
-    case IIMAGE2DRECT:
-    case UIMAGE2DRECT:
     case IMAGECUBE:
     case IIMAGECUBE:
     case UIMAGECUBE:
-    case IMAGEBUFFER:
-    case IIMAGEBUFFER:
-    case UIMAGEBUFFER:
-    case IMAGE1DARRAY:
-    case IIMAGE1DARRAY:
-    case UIMAGE1DARRAY:
     case IMAGE2DARRAY:
     case IIMAGE2DARRAY:
     case UIMAGE2DARRAY:
-        return firstGenerationImage();
+        return firstGenerationImage(true);
 
     case IMAGECUBEARRAY:
     case IIMAGECUBEARRAY:
@@ -1068,11 +1077,13 @@ int TScanContext::dMat()
     return identifierOrType();
 }
 
-int TScanContext::firstGenerationImage()
+int TScanContext::firstGenerationImage(bool inEs310)
 {
     afterType = true;
 
-    if (parseContext.symbolTable.atBuiltInLevel() || (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))))
+    if (parseContext.symbolTable.atBuiltInLevel() || 
+        (parseContext.profile != EEsProfile && (parseContext.version >= 420 || parseContext.extensionsTurnedOn(1, &GL_ARB_shader_image_load_store))) ||                                                     
+        (inEs310 && parseContext.profile == EEsProfile && parseContext.version >= 310))
         return keyword;
 
     if ((parseContext.profile == EEsProfile && parseContext.version >= 300) ||
diff --git a/glslang/MachineIndependent/ScanContext.h b/glslang/MachineIndependent/ScanContext.h
index cf2ad2a33bba09d5146645f6514cbc8b73189f22..bb8c42bbb56148d4d52fbfd01c174d845ad47b99 100644
--- a/glslang/MachineIndependent/ScanContext.h
+++ b/glslang/MachineIndependent/ScanContext.h
@@ -64,7 +64,7 @@ protected:
     int precisionKeyword();
     int matNxM();
     int dMat();
-    int firstGenerationImage();
+    int firstGenerationImage(bool inEs310);
     int secondGenerationImage();
 
     TParseContext& parseContext;
diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp
index b7c89f8e21d7967384def6799268745cffd3def0..4d3f22476dfbaa81d1adbb9bf1015735ea2cc164 100644
--- a/glslang/MachineIndependent/ShaderLang.cpp
+++ b/glslang/MachineIndependent/ShaderLang.cpp
@@ -78,11 +78,13 @@ int MapVersionToIndex(int version)
         case 420: return 10;
         case 430: return 11;
         case 440: return 12;
+        case 310: return 13;
+        case 450: return 14;
         default:       // |
             return  0; // |
         }              // |
 }                      // V
-const int VersionCount = 13;  // number of case statements above
+const int VersionCount = 15;  // number of case statements above
 
 int MapProfileToIndex(EProfile profile)
 {
@@ -197,7 +199,8 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable,  TS
     }
     if (profile != EEsProfile && version >= 150)
         InitializeStageSymbolTable(builtIns, version, profile, EShLangGeometry, infoSink, commonTable, symbolTables);
-    if (profile != EEsProfile && version >= 430)
+    if ((profile != EEsProfile && version >= 430) ||
+        (profile == EEsProfile && version >= 310))
         InitializeStageSymbolTable(builtIns, version, profile, EShLangCompute, infoSink, commonTable, symbolTables);
 
     return true;
@@ -303,9 +306,9 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
 
     // Get a good profile...
     if (profile == ENoProfile) {
-        if (version == 300) {
+        if (version == 300 || version == 310) {
             correct = false;
-            infoSink.info.message(EPrefixError, "#version: version 300 requires specifying the 'es' profile");
+            infoSink.info.message(EPrefixError, "#version: versions 300 and 310 require specifying the 'es' profile");
             profile = EEsProfile;
         } else if (version == 100)
             profile = EEsProfile;
@@ -322,16 +325,16 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
                 profile = EEsProfile;
             else
                 profile = ENoProfile;
-        } else if (version == 300) {
+        } else if (version == 300 || version == 310) {
             if (profile != EEsProfile) {
                 correct = false;
-                infoSink.info.message(EPrefixError, "#version: version 300 supports only the es profile");
+                infoSink.info.message(EPrefixError, "#version: versions 300 and 310 support only the es profile");
             }
             profile = EEsProfile;
         } else {
             if (profile == EEsProfile) {
                 correct = false;
-                infoSink.info.message(EPrefixError, "#version: only version 300 supports the es profile");
+                infoSink.info.message(EPrefixError, "#version: only version 300 and 310 support the es profile");
                 if (version >= FirstProfileVersion)
                     profile = ECoreProfile;
                 else
@@ -361,10 +364,11 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         }
         break;
     case EShLangCompute:
-        if (version < 430 || (profile != ECoreProfile && profile != ECompatibilityProfile)) {
+        if ((profile == EEsProfile && version < 310) ||
+            (profile != EEsProfile && version < 430)) {
             correct = false;
-            infoSink.info.message(EPrefixError, "#version: compute shaders require non-es profile and version 430 or above");
-            version = 430;
+            infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 430 or above");
+            version = profile == EEsProfile ? 310 : 430;
             profile = ECoreProfile;
         }
         break;
@@ -395,9 +399,21 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
         // versions are complete
         break;
 
-    default:
+    case 310:
+    case 330:
+    case 400:
+    case 410:
+    case 420:
+    case 430:
+    case 440:
+    case 450:
         infoSink.info << "Warning, version " << version << " is not yet complete; most version-specific features are present, but some are missing.\n";
         break;
+
+    default:
+        infoSink.info << "Warning, version " << version << " is unknown.\n";
+        break;
+
     }
 
     return correct;
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index e34231c4c6700bbdcb83930ec0425974e63517d2..c71c6e213d144db7cf35cbc6a6ccc95786a273af 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -1216,8 +1216,8 @@ storage_qualifier
         $$.qualifier.storage = EvqBuffer;
     }
     | SHARED {
-        parseContext.requireProfile($1.loc, ~EEsProfile, "shared");
-        parseContext.profileRequires($1.loc, ECoreProfile, 430, 0, "shared");
+        parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, 0, "shared");
+        parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared");
         parseContext.requireStage($1.loc, EShLangCompute, "shared");
         $$.init($1.loc);
         $$.qualifier.storage = EvqShared;
@@ -1964,6 +1964,7 @@ precision_qualifier
 struct_specifier
     : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
         TType* structure = new TType($5, *$2.string);
+        parseContext.structArrayCheck($2.loc, structure);
         TVariable* userTypeDef = new TVariable($2.string, *structure, true);
         if (! parseContext.symbolTable.insert(*userTypeDef))
             parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct");
@@ -2055,8 +2056,6 @@ struct_declarator
         $$.type->setFieldName(*$1.string);
     }
     | IDENTIFIER array_specifier {        
-        if (parseContext.profile == EEsProfile)
-            parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());
         parseContext.arrayDimCheck($1.loc, $2.arraySizes, 0);
 
         $$.type = new TType(EbtVoid);