Implement barrier() control-flow rules: in flow control, non-main, and post-return.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@29347 e7fa87d3-cd2b-0410-9028-fcbf551c1848
diff --git a/Test/400.tesc b/Test/400.tesc
index 46e408f..1f0126c 100644
--- a/Test/400.tesc
+++ b/Test/400.tesc
@@ -34,6 +34,31 @@
 

     gl_TessLevelOuter[3] = 3.2;

     gl_TessLevelInner[1] = 1.3;

+

+    if (a > 10)

+        barrier();           // ERROR

+    else

+        barrier();           // ERROR

+

+    barrier();

+

+    do {

+        barrier();           // ERROR

+    } while (a > 10);

+

+    switch (a) {

+    default:

+        barrier();           // ERROR

+        break;

+    }

+

+    {

+        barrier();

+    }

+

+    return;

+

+    barrier();               // ERROR

 }

 

 layout(vertices = 4) in;    // ERROR

@@ -42,6 +67,8 @@
 void foo()

 {

     gl_out[4].gl_PointSize;  // ERROR

+

+    barrier();                // ERROR

 }

 

 in vec2 ina;   // ERROR, not array

diff --git a/Test/430.comp b/Test/430.comp
index f022f8f..53b4617 100644
--- a/Test/430.comp
+++ b/Test/430.comp
@@ -34,6 +34,10 @@
     memoryBarrierImage();

     groupMemoryBarrier();

     value = int(values[gl_LocalInvocationIndex]);

+

+    int a;

+    if (a > 10)

+        barrier();

 }

 

 layout(location = 2) in vec3 v3;      // ERROR

@@ -60,4 +64,5 @@
 {

     ro.values[2] = 4.7;        // ERROR, readonly

     ro.values.length();

+    barrier();

 }

diff --git a/Test/baseResults/150.tesc.out b/Test/baseResults/150.tesc.out
index 1d3ce1d..87e0767 100644
--- a/Test/baseResults/150.tesc.out
+++ b/Test/baseResults/150.tesc.out
@@ -219,14 +219,20 @@
 ERROR: 0:7: 'ccw' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) 

 ERROR: 0:8: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) 

 ERROR: 0:10: 'patch' : can only use on output in tessellation-control shader 

-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: 0:47: 'in' : type must be an array: ina

-ERROR: 0:49: '[]' : tessellation input array size must be gl_MaxPatchVertices or implicitly sized 

-ERROR: 0:56: 'location' : overlapping use of location 4

-ERROR: 0:60: 'location' : overlapping use of location 4

-ERROR: 11 compilation errors.  No code generated.

+ERROR: 0:39: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:41: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:46: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:51: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:61: '' : tessellation control barrier() cannot be placed after a return from main() 

+ERROR: 0:64: 'vertices' : can only apply to 'out' 

+ERROR: 0:65: 'vertices' : cannot change previously set layout value 

+ERROR: 0:69: '[' :  array index out of range '4'

+ERROR: 0:71: '' : tessellation control barrier() must be in main() 

+ERROR: 0:74: 'in' : type must be an array: ina

+ERROR: 0:76: '[]' : tessellation input array size must be gl_MaxPatchVertices or implicitly sized 

+ERROR: 0:83: 'location' : overlapping use of location 4

+ERROR: 0:87: 'location' : overlapping use of location 4

+ERROR: 17 compilation errors.  No code generated.

 

 

 Shader version: 400

@@ -331,34 +337,68 @@
 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 (out float)

-0:44        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

-0:44          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

-0:44          Constant:

-0:44            4 (const int)

-0:44        Constant:

-0:44          1 (const int)

-0:64  Function Definition: foop( (void)

-0:64    Function Parameters: 

+0:38      Test condition and select (void)

+0:38        Condition

+0:38        Compare Greater Than (bool)

+0:38          'a' (int)

+0:38          Constant:

+0:38            10 (const int)

+0:38        true case

+0:39        Barrier (void)

+0:38        false case

+0:41        Barrier (void)

+0:43      Barrier (void)

+0:47      Loop with condition not tested first

+0:47        Loop Condition

+0:47        Compare Greater Than (bool)

+0:47          'a' (int)

+0:47          Constant:

+0:47            10 (const int)

+0:47        Loop Body

+0:46        Sequence

+0:46          Barrier (void)

+0:49      switch

+0:49      condition

+0:49        'a' (int)

+0:49      body

+0:49        Sequence

+0:50          default: 

+0:?           Sequence

+0:51            Barrier (void)

+0:52            Branch: Break

+0:56      Sequence

+0:56        Barrier (void)

+0:59      Branch: Return

+0:61      Barrier (void)

+0:67  Function Definition: foo( (void)

+0:67    Function Parameters: 

+0:69    Sequence

+0:69      gl_PointSize: direct index for structure (out float)

+0:69        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

+0:69          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

+0:69          Constant:

+0:69            4 (const int)

+0:69        Constant:

+0:69          1 (const int)

+0:71      Barrier (void)

+0:91  Function Definition: foop( (void)

+0:91    Function Parameters: 

 0:?     Sequence

-0:68      multiply second child into first child (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:69      move second child to first child (3-component vector of float)

-0:69        'pv3' (3-component vector of float)

-0:69        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:70      move second child to first child (double)

-0:70        'd' (double)

-0:70        Function Call: fma(d1;d1;d1; (double)

-0:70          'd' (double)

-0:70          'd' (double)

-0:70          'd' (double)

+0:95      multiply second child into first child (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:96      move second child to first child (3-component vector of float)

+0:96        'pv3' (3-component vector of float)

+0:96        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:97      move second child to first child (double)

+0:97        'd' (double)

+0:97        Function Call: fma(d1;d1;d1; (double)

+0:97          'd' (double)

+0:97          'd' (double)

+0:97          'd' (double)

 0:?   Linker Objects

 0:?     'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

 0:?     'outa' (4-element array of int)

@@ -1031,34 +1071,68 @@
 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 (out float)

-0:44        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

-0:44          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

-0:44          Constant:

-0:44            4 (const int)

-0:44        Constant:

-0:44          1 (const int)

-0:64  Function Definition: foop( (void)

-0:64    Function Parameters: 

+0:38      Test condition and select (void)

+0:38        Condition

+0:38        Compare Greater Than (bool)

+0:38          'a' (int)

+0:38          Constant:

+0:38            10 (const int)

+0:38        true case

+0:39        Barrier (void)

+0:38        false case

+0:41        Barrier (void)

+0:43      Barrier (void)

+0:47      Loop with condition not tested first

+0:47        Loop Condition

+0:47        Compare Greater Than (bool)

+0:47          'a' (int)

+0:47          Constant:

+0:47            10 (const int)

+0:47        Loop Body

+0:46        Sequence

+0:46          Barrier (void)

+0:49      switch

+0:49      condition

+0:49        'a' (int)

+0:49      body

+0:49        Sequence

+0:50          default: 

+0:?           Sequence

+0:51            Barrier (void)

+0:52            Branch: Break

+0:56      Sequence

+0:56        Barrier (void)

+0:59      Branch: Return

+0:61      Barrier (void)

+0:67  Function Definition: foo( (void)

+0:67    Function Parameters: 

+0:69    Sequence

+0:69      gl_PointSize: direct index for structure (out float)

+0:69        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

+0:69          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

+0:69          Constant:

+0:69            4 (const int)

+0:69        Constant:

+0:69          1 (const int)

+0:71      Barrier (void)

+0:91  Function Definition: foop( (void)

+0:91    Function Parameters: 

 0:?     Sequence

-0:68      multiply second child into first child (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:69      move second child to first child (3-component vector of float)

-0:69        'pv3' (3-component vector of float)

-0:69        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:70      move second child to first child (double)

-0:70        'd' (double)

-0:70        Function Call: fma(d1;d1;d1; (double)

-0:70          'd' (double)

-0:70          'd' (double)

-0:70          'd' (double)

+0:95      multiply second child into first child (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:96      move second child to first child (3-component vector of float)

+0:96        'pv3' (3-component vector of float)

+0:96        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:97      move second child to first child (double)

+0:97        'd' (double)

+0:97        Function Call: fma(d1;d1;d1; (double)

+0:97          'd' (double)

+0:97          'd' (double)

+0:97          'd' (double)

 0:8  Function Definition: main( (void)

 0:8    Function Parameters: 

 0:15  Function Definition: main( (void)

diff --git a/Test/baseResults/400.tesc.out b/Test/baseResults/400.tesc.out
index bd5d4b6..af2a414 100644
--- a/Test/baseResults/400.tesc.out
+++ b/Test/baseResults/400.tesc.out
@@ -4,14 +4,20 @@
 ERROR: 0:7: 'ccw' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) 

 ERROR: 0:8: 'fractional_even_spacing' : unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4) 

 ERROR: 0:10: 'patch' : can only use on output in tessellation-control shader 

-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: 0:47: 'in' : type must be an array: ina

-ERROR: 0:49: '[]' : tessellation input array size must be gl_MaxPatchVertices or implicitly sized 

-ERROR: 0:56: 'location' : overlapping use of location 4

-ERROR: 0:60: 'location' : overlapping use of location 4

-ERROR: 11 compilation errors.  No code generated.

+ERROR: 0:39: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:41: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:46: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:51: '' : tessellation control barrier() cannot be placed within flow control 

+ERROR: 0:61: '' : tessellation control barrier() cannot be placed after a return from main() 

+ERROR: 0:64: 'vertices' : can only apply to 'out' 

+ERROR: 0:65: 'vertices' : cannot change previously set layout value 

+ERROR: 0:69: '[' :  array index out of range '4'

+ERROR: 0:71: '' : tessellation control barrier() must be in main() 

+ERROR: 0:74: 'in' : type must be an array: ina

+ERROR: 0:76: '[]' : tessellation input array size must be gl_MaxPatchVertices or implicitly sized 

+ERROR: 0:83: 'location' : overlapping use of location 4

+ERROR: 0:87: 'location' : overlapping use of location 4

+ERROR: 17 compilation errors.  No code generated.

 

 

 Shader version: 400

@@ -116,34 +122,68 @@
 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 (out float)

-0:44        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

-0:44          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

-0:44          Constant:

-0:44            4 (const int)

-0:44        Constant:

-0:44          1 (const int)

-0:64  Function Definition: foop( (void)

-0:64    Function Parameters: 

+0:38      Test condition and select (void)

+0:38        Condition

+0:38        Compare Greater Than (bool)

+0:38          'a' (int)

+0:38          Constant:

+0:38            10 (const int)

+0:38        true case

+0:39        Barrier (void)

+0:38        false case

+0:41        Barrier (void)

+0:43      Barrier (void)

+0:47      Loop with condition not tested first

+0:47        Loop Condition

+0:47        Compare Greater Than (bool)

+0:47          'a' (int)

+0:47          Constant:

+0:47            10 (const int)

+0:47        Loop Body

+0:46        Sequence

+0:46          Barrier (void)

+0:49      switch

+0:49      condition

+0:49        'a' (int)

+0:49      body

+0:49        Sequence

+0:50          default: 

+0:?           Sequence

+0:51            Barrier (void)

+0:52            Branch: Break

+0:56      Sequence

+0:56        Barrier (void)

+0:59      Branch: Return

+0:61      Barrier (void)

+0:67  Function Definition: foo( (void)

+0:67    Function Parameters: 

+0:69    Sequence

+0:69      gl_PointSize: direct index for structure (out float)

+0:69        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

+0:69          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

+0:69          Constant:

+0:69            4 (const int)

+0:69        Constant:

+0:69          1 (const int)

+0:71      Barrier (void)

+0:91  Function Definition: foop( (void)

+0:91    Function Parameters: 

 0:?     Sequence

-0:68      multiply second child into first child (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:69      move second child to first child (3-component vector of float)

-0:69        'pv3' (3-component vector of float)

-0:69        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:70      move second child to first child (double)

-0:70        'd' (double)

-0:70        Function Call: fma(d1;d1;d1; (double)

-0:70          'd' (double)

-0:70          'd' (double)

-0:70          'd' (double)

+0:95      multiply second child into first child (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:96      move second child to first child (3-component vector of float)

+0:96        'pv3' (3-component vector of float)

+0:96        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:97      move second child to first child (double)

+0:97        'd' (double)

+0:97        Function Call: fma(d1;d1;d1; (double)

+0:97          'd' (double)

+0:97          'd' (double)

+0:97          'd' (double)

 0:?   Linker Objects

 0:?     'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out implicitly-sized array of float gl_ClipDistance})

 0:?     'outa' (4-element array of int)

@@ -268,34 +308,68 @@
 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 (out float)

-0:44        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

-0:44          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

-0:44          Constant:

-0:44            4 (const int)

-0:44        Constant:

-0:44          1 (const int)

-0:64  Function Definition: foop( (void)

-0:64    Function Parameters: 

+0:38      Test condition and select (void)

+0:38        Condition

+0:38        Compare Greater Than (bool)

+0:38          'a' (int)

+0:38          Constant:

+0:38            10 (const int)

+0:38        true case

+0:39        Barrier (void)

+0:38        false case

+0:41        Barrier (void)

+0:43      Barrier (void)

+0:47      Loop with condition not tested first

+0:47        Loop Condition

+0:47        Compare Greater Than (bool)

+0:47          'a' (int)

+0:47          Constant:

+0:47            10 (const int)

+0:47        Loop Body

+0:46        Sequence

+0:46          Barrier (void)

+0:49      switch

+0:49      condition

+0:49        'a' (int)

+0:49      body

+0:49        Sequence

+0:50          default: 

+0:?           Sequence

+0:51            Barrier (void)

+0:52            Branch: Break

+0:56      Sequence

+0:56        Barrier (void)

+0:59      Branch: Return

+0:61      Barrier (void)

+0:67  Function Definition: foo( (void)

+0:67    Function Parameters: 

+0:69    Sequence

+0:69      gl_PointSize: direct index for structure (out float)

+0:69        direct index (block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

+0:69          'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

+0:69          Constant:

+0:69            4 (const int)

+0:69        Constant:

+0:69          1 (const int)

+0:71      Barrier (void)

+0:91  Function Definition: foop( (void)

+0:91    Function Parameters: 

 0:?     Sequence

-0:68      multiply second child into first child (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:68        'pv3' (3-component vector of float)

-0:69      move second child to first child (3-component vector of float)

-0:69        'pv3' (3-component vector of float)

-0:69        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:69          'pv3' (3-component vector of float)

-0:70      move second child to first child (double)

-0:70        'd' (double)

-0:70        Function Call: fma(d1;d1;d1; (double)

-0:70          'd' (double)

-0:70          'd' (double)

-0:70          'd' (double)

+0:95      multiply second child into first child (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:95        'pv3' (3-component vector of float)

+0:96      move second child to first child (3-component vector of float)

+0:96        'pv3' (3-component vector of float)

+0:96        Function Call: fma(vf3;vf3;vf3; (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:96          'pv3' (3-component vector of float)

+0:97      move second child to first child (double)

+0:97        'd' (double)

+0:97        Function Call: fma(d1;d1;d1; (double)

+0:97          'd' (double)

+0:97          'd' (double)

+0:97          'd' (double)

 0:?   Linker Objects

 0:?     'gl_out' (out 4-element array of block{out 4-component vector of float gl_Position, out float gl_PointSize, out 1-element array of float gl_ClipDistance})

 0:?     'outa' (4-element array of int)

diff --git a/Test/baseResults/430.comp.out b/Test/baseResults/430.comp.out
index b1fed46..0453641 100644
--- a/Test/baseResults/430.comp.out
+++ b/Test/baseResults/430.comp.out
@@ -3,17 +3,17 @@
 ERROR: 0:4: 'local_size' : cannot change previously set size 

 ERROR: 0:5: 'local_size' : too large; see gl_MaxComputeWorkGroupSize 

 ERROR: 0:23: 'values' : only the last member of a buffer block can be run-time sized 

-ERROR: 0:39: 'in' : global storage input qualifier cannot be used in a compute shader 

-ERROR: 0:39: 'location qualifier on input' : not supported in this stage: compute

-ERROR: 0:40: 'in' : global storage input qualifier cannot be used in a compute shader 

-ERROR: 0:41: 'out' : global storage output qualifier cannot be used in a compute shader 

-ERROR: 0:44: 'shared' : cannot apply layout qualifiers to a shared variable 

-ERROR: 0:44: 'location' : can only appy to uniform, buffer, in, or out storage qualifiers 

-ERROR: 0:45: 'shared' :  cannot initialize this type of qualifier  

-ERROR: 0:47: 'local_size' : can only apply to 'in' 

-ERROR: 0:47: 'local_size' : can only apply to 'in' 

-ERROR: 0:47: 'local_size' : can only apply to 'in' 

-ERROR: 0:61: 'assign' :  l-value required "ro" (can't modify a readonly buffer)

+ERROR: 0:43: 'in' : global storage input qualifier cannot be used in a compute shader 

+ERROR: 0:43: 'location qualifier on input' : not supported in this stage: compute

+ERROR: 0:44: 'in' : global storage input qualifier cannot be used in a compute shader 

+ERROR: 0:45: 'out' : global storage output qualifier cannot be used in a compute shader 

+ERROR: 0:48: 'shared' : cannot apply layout qualifiers to a shared variable 

+ERROR: 0:48: 'location' : can only appy to uniform, buffer, in, or out storage qualifiers 

+ERROR: 0:49: 'shared' :  cannot initialize this type of qualifier  

+ERROR: 0:51: 'local_size' : can only apply to 'in' 

+ERROR: 0:51: 'local_size' : can only apply to 'in' 

+ERROR: 0:51: 'local_size' : can only apply to 'in' 

+ERROR: 0:65: 'assign' :  l-value required "ro" (can't modify a readonly buffer)

 ERROR: 14 compilation errors.  No code generated.

 

 

@@ -42,24 +42,33 @@
 0:36              Constant:

 0:36                1 (const uint)

 0:36            'gl_LocalInvocationIndex' (in uint)

-0:59  Function Definition: foo( (void)

-0:59    Function Parameters: 

-0:61    Sequence

-0:61      move second child to first child (float)

-0:61        direct index (layout(column_major shared ) float)

-0:61          values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

-0:61            'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

-0:61            Constant:

-0:61              1 (const int)

-0:61          Constant:

-0:61            2 (const int)

-0:61        Constant:

-0:61          4.700000

-0:62      array length (int)

-0:62        values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

-0:62          'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

-0:62          Constant:

-0:62            1 (const int)

+0:39      Test condition and select (void)

+0:39        Condition

+0:39        Compare Greater Than (bool)

+0:39          'a' (int)

+0:39          Constant:

+0:39            10 (const int)

+0:39        true case

+0:40        Barrier (void)

+0:63  Function Definition: foo( (void)

+0:63    Function Parameters: 

+0:65    Sequence

+0:65      move second child to first child (float)

+0:65        direct index (layout(column_major shared ) float)

+0:65          values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

+0:65            'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

+0:65            Constant:

+0:65              1 (const int)

+0:65          Constant:

+0:65            2 (const int)

+0:65        Constant:

+0:65          4.700000

+0:66      array length (int)

+0:66        values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

+0:66          'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

+0:66          Constant:

+0:66            1 (const int)

+0:67      Barrier (void)

 0:?   Linker Objects

 0:?     'gl_WorkGroupSize' (const 3-component vector of uint)

 0:?       2 (const uint)

@@ -109,24 +118,33 @@
 0:36              Constant:

 0:36                1 (const uint)

 0:36            'gl_LocalInvocationIndex' (in uint)

-0:59  Function Definition: foo( (void)

-0:59    Function Parameters: 

-0:61    Sequence

-0:61      move second child to first child (float)

-0:61        direct index (layout(column_major shared ) float)

-0:61          values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

-0:61            'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

-0:61            Constant:

-0:61              1 (const int)

-0:61          Constant:

-0:61            2 (const int)

-0:61        Constant:

-0:61          4.700000

-0:62      array length (int)

-0:62        values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

-0:62          'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

-0:62          Constant:

-0:62            1 (const int)

+0:39      Test condition and select (void)

+0:39        Condition

+0:39        Compare Greater Than (bool)

+0:39          'a' (int)

+0:39          Constant:

+0:39            10 (const int)

+0:39        true case

+0:40        Barrier (void)

+0:63  Function Definition: foo( (void)

+0:63    Function Parameters: 

+0:65    Sequence

+0:65      move second child to first child (float)

+0:65        direct index (layout(column_major shared ) float)

+0:65          values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

+0:65            'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

+0:65            Constant:

+0:65              1 (const int)

+0:65          Constant:

+0:65            2 (const int)

+0:65        Constant:

+0:65          4.700000

+0:66      array length (int)

+0:66        values: direct index for structure (layout(column_major shared ) buffer implicitly-sized array of float)

+0:66          'ro' (layout(column_major shared ) readonly buffer block{layout(column_major shared ) buffer int value, layout(column_major shared ) buffer implicitly-sized array of float values})

+0:66          Constant:

+0:66            1 (const int)

+0:67      Barrier (void)

 0:?   Linker Objects

 0:?     'gl_WorkGroupSize' (const 3-component vector of uint)

 0:?       2 (const uint)

diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index f67a6f5..0837553 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -51,7 +51,8 @@
                              bool fc, EShMessages m) :
             intermediate(interm), symbolTable(symt), infoSink(is), language(L),
             version(v), profile(p), forwardCompatible(fc), messages(m),
-            contextPragma(true, false), loopNestingLevel(0), controlFlowNestingLevel(0), structNestingLevel(0),
+            contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0),
+            postMainReturn(false),
             tokensBeforeEOF(false), limits(resources.limits), currentScanner(0),
             numErrors(0), parsingBuiltins(pb), afterEOF(false),
             atomicUintOffsets(0), anyIndexLimits(false)
@@ -915,7 +916,9 @@
         if (function.getType().getBasicType() != EbtVoid)
             error(loc, "", function.getType().getBasicTypeString().c_str(), "main function cannot return a value");
         intermediate.addMainCount();
-    }
+        inMain = true;
+    } else
+        inMain = false;
 
     //
     // New symbol table scope for body of function plus its arguments
@@ -953,7 +956,9 @@
     }
     intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
     loopNestingLevel = 0;
+    statementNestingLevel = 0;
     controlFlowNestingLevel = 0;
+    postMainReturn = false;
 
     return paramNodes;
 }
@@ -1045,6 +1050,7 @@
             op = fnCandidate->getBuiltInOp();
             if (builtIn && op != EOpNull) {
                 // A function call mapped to a built-in operation.
+                checkLocation(loc, op);
                 result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments, fnCandidate->getType());
                 if (result == 0)  {
                     error(arguments->getLoc(), " wrong operand type", "Internal Error",
@@ -1091,6 +1097,25 @@
     return result;
 }
 
+// See if the operation is being done in an illegal location.
+void TParseContext::checkLocation(TSourceLoc loc, TOperator op)
+{
+    switch (op) {
+    case EOpBarrier:
+        if (language == EShLangTessControl) {
+            if (controlFlowNestingLevel > 0)
+                error(loc, "tessellation control barrier() cannot be placed within flow control", "", "");
+            if (! inMain)
+                error(loc, "tessellation control barrier() must be in main()", "", "");
+            else if (postMainReturn)
+                error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", "");
+        }
+        break;
+    default:
+        break;
+    }
+}
+
 // Finish processing object.length(). This started earlier in handleDotDereference(), where
 // the ".length" part was recognized and semantically checked, and finished here where the 
 // function syntax "()" is recognized.
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 6b1e72f..388c16b 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -101,6 +101,7 @@
     TFunction* handleFunctionDeclarator(TSourceLoc loc, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
     TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*);
+    void checkLocation(TSourceLoc, TOperator);
     TIntermTyped* handleLengthMethod(TSourceLoc, TFunction*, TIntermNode*);
     void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
@@ -245,9 +246,12 @@
     struct TPragma contextPragma;
     int loopNestingLevel;        // 0 if outside all loops
     int structNestingLevel;      // 0 if outside blocks and structures
-    int controlFlowNestingLevel; // 0 if outside all flow control or compound statements; also counts compound statements
+    int controlFlowNestingLevel; // 0 if outside all flow control
+    int statementNestingLevel;   // 0 if outside all flow control or compound statements
     TList<TIntermSequence*> switchSequenceStack;  // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
-    TList<int> switchLevel;      // the controlFlowNestingLevel the current switch statement is at, which must match the level of its case statements
+    TList<int> switchLevel;      // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
+    bool inMain;                 // if inside a function, true if the function is main
+    bool postMainReturn;         // if inside a function, true if the function is main and this is after a return statement
     const TType* currentFunctionType;  // the return type of the function that's currently being parsed
     bool functionReturnsValue;   // true if a non-void function has a return
     const TString* blockName;
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index aa8d75d..bda83c5 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -2065,11 +2065,11 @@
     : LEFT_BRACE RIGHT_BRACE { $$ = 0; }

     | LEFT_BRACE {

         parseContext.symbolTable.push();

-        ++parseContext.controlFlowNestingLevel;

+        ++parseContext.statementNestingLevel;

     }

       statement_list {

         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);

-        --parseContext.controlFlowNestingLevel;

+        --parseContext.statementNestingLevel;

     }

       RIGHT_BRACE {

         if ($3 && $3->getAsAggregate())

@@ -2084,13 +2084,21 @@
     ;

 

 statement_scoped

-    : compound_statement  { $$ = $1; }

+    : {

+        ++parseContext.controlFlowNestingLevel;

+    }

+      compound_statement  {

+        --parseContext.controlFlowNestingLevel;

+        $$ = $2;

+    }

     | {

         parseContext.symbolTable.push();

+        ++parseContext.statementNestingLevel;

         ++parseContext.controlFlowNestingLevel;

     }

       simple_statement {

         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);

+        --parseContext.statementNestingLevel;

         --parseContext.controlFlowNestingLevel;

         $$ = $2;

     }

@@ -2171,8 +2179,9 @@
     : SWITCH LEFT_PAREN expression RIGHT_PAREN {

         // start new switch sequence on the switch stack

         ++parseContext.controlFlowNestingLevel;

+        ++parseContext.statementNestingLevel;

         parseContext.switchSequenceStack.push_back(new TIntermSequence);

-        parseContext.switchLevel.push_back(parseContext.controlFlowNestingLevel);

+        parseContext.switchLevel.push_back(parseContext.statementNestingLevel);

         parseContext.symbolTable.push();

     }

     LEFT_BRACE switch_statement_list RIGHT_BRACE {

@@ -2181,6 +2190,7 @@
         parseContext.switchSequenceStack.pop_back();

         parseContext.switchLevel.pop_back();

         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);

+        --parseContext.statementNestingLevel;

         --parseContext.controlFlowNestingLevel;

     }

     ;

@@ -2199,7 +2209,7 @@
         $$ = 0;

         if (parseContext.switchLevel.size() == 0)

             parseContext.error($1.loc, "cannot appear outside switch statement", "case", "");

-        else if (parseContext.switchLevel.back() != parseContext.controlFlowNestingLevel)

+        else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)

             parseContext.error($1.loc, "cannot be nested inside control flow", "case", "");

         else {

             parseContext.constantValueCheck($2, "case");

@@ -2211,7 +2221,7 @@
         $$ = 0;

         if (parseContext.switchLevel.size() == 0)

             parseContext.error($1.loc, "cannot appear outside switch statement", "default", "");

-        else if (parseContext.switchLevel.back() != parseContext.controlFlowNestingLevel)

+        else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel)

             parseContext.error($1.loc, "cannot be nested inside control flow", "default", "");

         else

             $$ = parseContext.intermediate.addBranch(EOpDefault, $1.loc);

@@ -2224,16 +2234,19 @@
             parseContext.error($1.loc, "while loops not available", "limitation", "");

         parseContext.symbolTable.push();

         ++parseContext.loopNestingLevel;

+        ++parseContext.statementNestingLevel;

         ++parseContext.controlFlowNestingLevel;

     }

       condition RIGHT_PAREN statement_no_new_scope {

         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);

         $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc);

         --parseContext.loopNestingLevel;

+        --parseContext.statementNestingLevel;

         --parseContext.controlFlowNestingLevel;

     }

     | DO {

         ++parseContext.loopNestingLevel;

+        ++parseContext.statementNestingLevel;

         ++parseContext.controlFlowNestingLevel;

     }

       statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {

@@ -2244,11 +2257,13 @@
 

         $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);

         --parseContext.loopNestingLevel;

+        --parseContext.statementNestingLevel;

         --parseContext.controlFlowNestingLevel;

     }

     | FOR LEFT_PAREN {

         parseContext.symbolTable.push();

         ++parseContext.loopNestingLevel;

+        ++parseContext.statementNestingLevel;

         ++parseContext.controlFlowNestingLevel;

     }

       for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {

@@ -2260,6 +2275,7 @@
         $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);

         $$->getAsAggregate()->setOperator(EOpSequence);

         --parseContext.loopNestingLevel;

+        --parseContext.statementNestingLevel;

         --parseContext.controlFlowNestingLevel;

     }

     ;

@@ -2308,6 +2324,8 @@
         $$ = parseContext.intermediate.addBranch(EOpReturn, $1.loc);

         if (parseContext.currentFunctionType->getBasicType() != EbtVoid)

             parseContext.error($1.loc, "non-void function must return a value", "return", "");

+        if (parseContext.inMain)

+            parseContext.postMainReturn = true;

     }

     | RETURN expression SEMICOLON {

         parseContext.functionReturnsValue = true;