diff --git a/Test/420.vert b/Test/420.vert
index 3f4fa6990e145809ba4a39cde7c9b6c1b760b277..04dd17092b431a8080cc8b4549fde18080974eb5 100644
--- a/Test/420.vert
+++ b/Test/420.vert
@@ -12,6 +12,23 @@ smooth flat out vec4 rep;      // ERROR, replicating interpolation qualification
 centroid sample out vec4 rep2; // ERROR, replicating auxiliary qualification
 in uniform vec4 rep3;          // ERROR, replicating storage qualification
 
+int anonconst;
+const int aconst = 5;
+const int a = aconst;
+const int b = anonconst;       // ERROR at global scope
+
+const int foo()                // ERROR, no const functions
+{
+    const int a = aconst;
+    const int b = anonconst;
+    const int c = a;          // still compile-time const
+    const int d = b;          // not a compile-time const
+    float x[c];               // okay
+    float y[d];               // ERROR
+
+    return b;
+}
+
 void main()
 {
     int i;
diff --git a/Test/baseResults/120.vert.out b/Test/baseResults/120.vert.out
index bb956dea9e14444b9828ae7c4738c3e3bf5db1a4..9f499f87b65a2f6705c766c354297612dfab49f0 100644
--- a/Test/baseResults/120.vert.out
+++ b/Test/baseResults/120.vert.out
@@ -24,14 +24,16 @@ ERROR: 0:39: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:40: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:40: 'constructor' : array constructor needs one argument per array element 
 ERROR: 0:40: 'arrays of arrays' : not supported with this profile: none
+ERROR: 0:40: '=' :  cannot convert from 'const float' to '2-element array of float'
 ERROR: 0:41: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:41: 'constructor' : array constructor needs one argument per array element 
 ERROR: 0:41: 'arrays of arrays' : not supported with this profile: none
+ERROR: 0:41: '=' :  cannot convert from 'const float' to '2-element array of float'
 ERROR: 0:50: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:51: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:52: 'arrays of arrays' : not supported with this profile: none
 ERROR: 0:53: 'arrays of arrays' : not supported with this profile: none
-ERROR: 32 compilation errors.  No code generated.
+ERROR: 34 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
 0:15  Function Definition: main( (void)
@@ -75,14 +77,6 @@ ERROR: node is still EOpNull!
 0:32          'a3' (int)
 0:32          Constant:
 0:32            12 (const int)
-0:40      Sequence
-0:40        move second child to first child (2-element array of float)
-0:40          'md9' (2-element array of float)
-0:40          Construct float (const 2-element array of float)
-0:41      Sequence
-0:41        move second child to first child (2-element array of float)
-0:41          'md11' (2-element array of float)
-0:41          Construct float (const 2-element array of float)
 0:43      move second child to first child (float)
 0:43        'gl_PointSize' (invariant gl_PointSize float)
 0:43        Constant:
diff --git a/Test/baseResults/420.tese.out b/Test/baseResults/420.tese.out
index 415129bf22fd9e163ee86474bce1f79dfe9200fc..2b5af43d29c0a9b3325d6365aed7c2554106020a 100644
--- a/Test/baseResults/420.tese.out
+++ b/Test/baseResults/420.tese.out
@@ -8,10 +8,11 @@ ERROR: 0:27: '=' :  cannot convert from 'const bool' to 'int'
 ERROR: 0:28: 'constructor' :  cannot convert parameter 2 from 'const float' to '4-component vector of float'
 ERROR: 0:29: 'constructor' :  cannot convert parameter 2 from 'const 2X2 matrix of float' to 'const 4-component vector of float'
 ERROR: 0:29: 'const 2-element array of 4-component vector of float' : cannot construct with these arguments 
+ERROR: 0:29: '=' :  cannot convert from 'const float' to '2-element array of 4-component vector of float'
 ERROR: 0:30: 'initializer list' : wrong number of matrix columns: 4X2 matrix of float
 ERROR: 0:40: 'constructor' :  cannot convert parameter 1 from 'float' to 'structure'
 ERROR: 0:58: 'initializer list' : wrong number of structure members 
-ERROR: 12 compilation errors.  No code generated.
+ERROR: 13 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
 0:4  Sequence
@@ -34,10 +35,6 @@ ERROR: node is still EOpNull!
 0:20      Constant:
 0:20        1.000000
 0:20        3 (const int)
-0:29  Sequence
-0:29    move second child to first child (2-element array of 4-component vector of float)
-0:29      'b4' (2-element array of 4-component vector of float)
-0:29      Construct vec4 (const 2-element array of 4-component vector of float)
 0:42  Sequence
 0:42    move second child to first child (5-element array of float)
 0:42      'b5' (5-element array of float)
diff --git a/Test/baseResults/420.vert.out b/Test/baseResults/420.vert.out
index 6703561aa7dc4d8268a60c177281f8c6b2690e31..4201808d5212d44d3e3e7ee3437b1ec1b519b5b7 100644
--- a/Test/baseResults/420.vert.out
+++ b/Test/baseResults/420.vert.out
@@ -5,39 +5,56 @@ ERROR: 0:7: '' : vertex input cannot be further qualified
 ERROR: 0:11: '' : can only have one interpolation qualifier (flat, smooth, noperspective) 
 ERROR: 0:12: '' : can only have one auxiliary qualifier (centroid, patch, and sample) 
 ERROR: 0:13: 'uniform' : too many storage qualifiers 
-ERROR: 0:21: 'j' : undeclared identifier 
-ERROR: 0:21: '=' :  cannot convert from 'float' to 'int'
-ERROR: 0:22: 'k' : undeclared identifier 
-ERROR: 0:22: '=' :  cannot convert from 'float' to 'int'
-ERROR: 0:23: 'j' : undeclared identifier 
-ERROR: 0:23: '=' :  cannot convert from 'float' to 'int'
-ERROR: 0:27: 'jj' : undeclared identifier 
-ERROR: 0:27: '=' :  cannot convert from 'float' to 'int'
-ERROR: 13 compilation errors.  No code generated.
+ERROR: 0:18: '=' : global const initializers must be constant 'const int'
+ERROR: 0:20: 'const' : no qualifiers allowed for function return 
+ERROR: 0:27: '' : constant expression required 
+ERROR: 0:27: '' : array size must be a constant integer expression 
+ERROR: 0:38: 'j' : undeclared identifier 
+ERROR: 0:38: '=' :  cannot convert from 'float' to 'int'
+ERROR: 0:39: 'k' : undeclared identifier 
+ERROR: 0:39: '=' :  cannot convert from 'float' to 'int'
+ERROR: 0:40: 'j' : undeclared identifier 
+ERROR: 0:40: '=' :  cannot convert from 'float' to 'int'
+ERROR: 0:44: 'jj' : undeclared identifier 
+ERROR: 0:44: '=' :  cannot convert from 'float' to 'int'
+ERROR: 17 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
-0:15  Function Definition: main( (void)
-0:15    Function Parameters: 
+0:20  Function Definition: foo( (const int)
+0:20    Function Parameters: 
 0:?     Sequence
-0:18      Test condition and select (void)
-0:18        Condition
-0:18        Compare Equal (bool)
-0:18          'i' (int)
-0:18          Constant:
-0:18            3 (const int)
-0:18        true case
-0:19        Sequence
-0:19          move second child to first child (int)
-0:19            'j' (int)
-0:19            'i' (int)
-0:25      Loop with condition tested first
-0:25        Loop Condition
-0:25        Constant:
-0:25          true (const bool)
-0:25        No loop body
-0:30  Function Definition: bar(vf4; (void)
-0:30    Function Parameters: 
-0:30      'v' (in 4-component vector of float)
+0:23      Sequence
+0:23        move second child to first child (int)
+0:23          'b' (const (read only) int)
+0:23          'anonconst' (int)
+0:25      Sequence
+0:25        move second child to first child (int)
+0:25          'd' (const (read only) int)
+0:25          'b' (const (read only) int)
+0:29      Branch: Return with expression
+0:29        'b' (const (read only) int)
+0:32  Function Definition: main( (void)
+0:32    Function Parameters: 
+0:?     Sequence
+0:35      Test condition and select (void)
+0:35        Condition
+0:35        Compare Equal (bool)
+0:35          'i' (int)
+0:35          Constant:
+0:35            3 (const int)
+0:35        true case
+0:36        Sequence
+0:36          move second child to first child (int)
+0:36            'j' (int)
+0:36            'i' (int)
+0:42      Loop with condition tested first
+0:42        Loop Condition
+0:42        Constant:
+0:42          true (const bool)
+0:42        No loop body
+0:47  Function Definition: bar(vf4; (void)
+0:47    Function Parameters: 
+0:47      'v' (in 4-component vector of float)
 0:?   Linker Objects
 0:?     'v2' (smooth out 2-component vector of float)
 0:?     'bad' (in 10-element array of 4-component vector of float)
@@ -48,6 +65,12 @@ ERROR: node is still EOpNull!
 0:?     'rep' (smooth flat out 4-component vector of float)
 0:?     'rep2' (centroid smooth sample out 4-component vector of float)
 0:?     'rep3' (in 4-component vector of float)
+0:?     'anonconst' (int)
+0:?     'aconst' (const int)
+0:?       5 (const int)
+0:?     'a' (const int)
+0:?       5 (const int)
+0:?     'b' (int)
 0:?     'gl_VertexID' (gl_VertexId int)
 0:?     'gl_InstanceID' (gl_InstanceId int)
 
diff --git a/Test/baseResults/array.frag.out b/Test/baseResults/array.frag.out
index b87a9bf0982f75fb2ff444b02688e7bbec70fafa..3640184404062cc355a21c640a538d3bb85b7083 100644
--- a/Test/baseResults/array.frag.out
+++ b/Test/baseResults/array.frag.out
@@ -8,7 +8,7 @@ ERROR: 0:42: '[' :  array index out of range '5'
 ERROR: 0:45: '[' :  array index out of range '1000'
 ERROR: 0:46: '[' :  array index out of range '-1'
 ERROR: 0:52: '[' :  array index '2' out of range
-ERROR: 0:54: 'const' :  non-matching types for const initializer  
+ERROR: 0:54: 'const' : non-matching or non-convertible constant type for const initializer 
 ERROR: 0:56: '=' :  cannot convert from 'const 2-element array of int' to '3-element array of int'
 ERROR: 0:57: '[]' : scalar integer expression required 
 ERROR: 0:57: '[' :  array index out of range '-858993459'
diff --git a/Test/baseResults/constErrors.frag.out b/Test/baseResults/constErrors.frag.out
index bd249e2fc1af5939b156f18fae784a6dba8c75c9..48ec2499f60fd2788a0f1907d95ee745159446ea 100644
--- a/Test/baseResults/constErrors.frag.out
+++ b/Test/baseResults/constErrors.frag.out
@@ -1,18 +1,23 @@
 Warning, version 330 is not yet complete; some version-specific features are present, but many are missing.
-ERROR: 0:14: '=' :  assigning non-constant to 'const int'
+ERROR: 0:14: 'non-constant initializer' : not supported for this version or the enabled extensions 
 ERROR: 0:17: '' : constant expression required 
 ERROR: 0:17: '' : array size must be a constant integer expression 
 ERROR: 0:18: '' : constant expression required 
 ERROR: 0:18: '' : array size must be a constant integer expression 
 ERROR: 0:19: '' : constant expression required 
 ERROR: 0:19: '' : array size must be a constant integer expression 
-ERROR: 0:27: '=' :  assigning non-constant to 'const structure'
-ERROR: 0:33: '=' :  assigning non-constant to 'const structure'
+ERROR: 0:27: '=' : global const initializers must be constant 'const structure'
+ERROR: 0:33: '=' : global const initializers must be constant 'const structure'
 ERROR: 9 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
 0:10  Function Definition: main( (void)
 0:10    Function Parameters: 
+0:?     Sequence
+0:14      Sequence
+0:14        move second child to first child (int)
+0:14          'a3' (const (read only) int)
+0:14          'uniformInt' (uniform int)
 0:?   Linker Objects
 0:?     'inVar' (smooth in 4-component vector of float)
 0:?     'outVar' (out 4-component vector of float)
@@ -21,4 +26,6 @@ ERROR: node is still EOpNull!
 0:?     'uniformInt' (uniform int)
 0:?     's' (structure)
 0:?     's2' (structure)
+0:?     'f' (const float)
+0:?       3.000000
 
diff --git a/Test/baseResults/matrixError.vert.out b/Test/baseResults/matrixError.vert.out
index 65f623e44d405dfcb4c3bc4a96fc12b899b2996b..fa5a82bd9fab9df0ae53339bb435afb06cb3bbd6 100644
--- a/Test/baseResults/matrixError.vert.out
+++ b/Test/baseResults/matrixError.vert.out
@@ -1,6 +1,6 @@
 Warning, version 120 is not yet complete; most features are present, but a few are missing.
 ERROR: 0:10: 'constructor' : too many arguments 
-ERROR: 0:7: '=' :  cannot assign to 'const 2X4 matrix of float'
+ERROR: 0:7: 'const' : non-matching or non-convertible constant type for const initializer 
 ERROR: 0:17: 'assign' :  cannot convert from '2-component vector of float' to '3-component vector of float'
 ERROR: 0:18: 'assign' :  cannot convert from '2-component vector of float' to '3-component vector of float'
 ERROR: 0:19: '.' : field selection not allowed on matrix 
diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out
index 9eb9566b0e416afcb750bb2512b6eab71416da1a..a0e46f846786bececc11ec17c5ffff8d08ef32ce 100644
--- a/Test/baseResults/specExamples.frag.out
+++ b/Test/baseResults/specExamples.frag.out
@@ -22,6 +22,7 @@ ERROR: 0:115: 'depth_greater' : unrecognized layout identifier
 ERROR: 0:118: 'depth_less' : unrecognized layout identifier 
 ERROR: 0:121: 'depth_unchanged' : unrecognized layout identifier 
 ERROR: 0:150: 'constructor' : constructing from a non-dereferenced array 
+ERROR: 0:150: '=' :  cannot convert from 'const float' to '3-element array of 4-component vector of float'
 ERROR: 0:152: 'constructor' :  cannot convert parameter 1 from 'const 2-element array of 4-component vector of float' to '4-component vector of float'
 ERROR: 0:172: 'x' : undeclared identifier 
 ERROR: 0:172: '[]' : scalar integer expression required 
@@ -42,16 +43,12 @@ ERROR: 0:178: 'a' :  dot operator requires structure, array, vector, or matrix o
 ERROR: 0:178: 'length' :  dot operator requires structure, array, vector, or matrix on left hand side 
 ERROR: 0:178: '' : function call, method, or subroutine call expected 
 ERROR: 0:178: '' : no matching overloaded function found 
-ERROR: 0:193: '=' :  cannot convert from 'const int' to 'structure'
 ERROR: 0:198: 'e' : redefinition 
-ERROR: 0:217: '=' :  cannot convert from 'const float' to 'unsized array of float'
-ERROR: 0:219: '=' :  cannot convert from 'unsized array of float' to '5-element array of float'
-ERROR: 0:223: '=' :  assigning non-constant to 'const float'
 ERROR: 0:226: 'in' : not allowed in nested scope 
 ERROR: 0:227: 'in' : not allowed in nested scope 
 ERROR: 0:228: 'in' : not allowed in nested scope 
 ERROR: 0:232: 'out' : not allowed in nested scope 
-ERROR: 52 compilation errors.  No code generated.
+ERROR: 49 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
 0:5  Sequence
@@ -166,10 +163,6 @@ ERROR: node is still EOpNull!
 0:149              0.100000
 0:149              0.100000
 0:149              0.100000
-0:150        Sequence
-0:150          move second child to first child (3-element array of 4-component vector of float)
-0:150            'a3' (3-element array of 4-component vector of float)
-0:150            Construct vec4 (3-element array of 4-component vector of float)
 0:?       Sequence
 0:159        Sequence
 0:159          Sequence
@@ -235,6 +228,14 @@ ERROR: node is still EOpNull!
 0:219          move second child to first child (5-element array of float)
 0:219            'd' (5-element array of float)
 0:219            'b' (5-element array of float)
+0:?       Sequence
+0:223        Sequence
+0:223          move second child to first child (float)
+0:223            'ceiling' (const (read only) float)
+0:223            Convert int to float (float)
+0:223              add (int)
+0:223                'a' (int)
+0:223                'b' (int)
 0:?   Linker Objects
 0:?     'a' (int)
 0:?     'b' (int)
diff --git a/Test/baseResults/specExamples.vert.out b/Test/baseResults/specExamples.vert.out
index 5edf37f6e016e3aab132350089b6fad042b1f3e1..c06df108c5655cf0909e63a44f4296ecd6e86672 100644
--- a/Test/baseResults/specExamples.vert.out
+++ b/Test/baseResults/specExamples.vert.out
@@ -46,11 +46,10 @@ ERROR: 0:164: 'func' : no matching overloaded function found
 ERROR: 0:166: 'x' :  dot operator requires structure, array, vector, or matrix on left hand side 
 ERROR: 0:166: 'func2' : no matching overloaded function found 
 ERROR: 0:167: 'x' :  dot operator requires structure, array, vector, or matrix on left hand side 
-ERROR: 0:191: '=' :  cannot convert from 'const 4-component vector of float' to '2-element array of 4-component vector of float'
 ERROR: 0:192: 'constructor' : constructing from a non-dereferenced array 
 ERROR: 0:193: 'constructor' : constructing from a non-dereferenced array 
 ERROR: 0:194: 'constructor' : constructing from a non-dereferenced array 
-ERROR: 51 compilation errors.  No code generated.
+ERROR: 50 compilation errors.  No code generated.
 
 ERROR: node is still EOpNull!
 0:134  Function Definition: funcA(I21; (4-component vector of float)
@@ -244,9 +243,12 @@ ERROR: node is still EOpNull!
 0:191              1.000000
 0:191              1.000000
 0:191              1.000000
-0:192        Construct vec4 (3-element array of 4-component vector of float)
-0:193        Construct vec4 (3-element array of 4-component vector of float)
-0:194        Construct vec4 (3-element array of 4-component vector of float)
+0:192        Constant:
+0:192          0.000000
+0:193        Constant:
+0:193          0.000000
+0:194        Constant:
+0:194          0.000000
 0:?   Linker Objects
 0:?     'Coords' (out block)
 0:?     '__anon__0' (out block)
diff --git a/Test/baseResults/uint.frag.out b/Test/baseResults/uint.frag.out
index 2a14b8ad170ead4b5993ffabc36acfdc513e194d..428df239b1c03dd0aa31947dd8f9955b3f06336c 100644
--- a/Test/baseResults/uint.frag.out
+++ b/Test/baseResults/uint.frag.out
@@ -1,9 +1,9 @@
 ERROR: 0:2: 'uint' : must be qualified as flat in
 ERROR: 0:6: 'in' : cannot be bool 
-ERROR: 0:20: 'const' :  non-matching types for const initializer  
-ERROR: 0:24: 'const' :  non-matching types for const initializer  
-ERROR: 0:34: 'const' :  non-matching types for const initializer  
-ERROR: 0:37: 'const' :  non-matching types for const initializer  
+ERROR: 0:20: 'const' : non-matching or non-convertible constant type for const initializer 
+ERROR: 0:24: 'const' : non-matching or non-convertible constant type for const initializer 
+ERROR: 0:34: 'const' : non-matching or non-convertible constant type for const initializer 
+ERROR: 0:37: 'const' : non-matching or non-convertible constant type for const initializer 
 ERROR: 0:48: '=' :  cannot convert from 'const int' to 'mediump uint'
 ERROR: 0:51: '=' :  cannot convert from 'const int' to 'mediump uint'
 ERROR: 0:63: 'float' : type requires declaration of default precision qualifier 
diff --git a/Test/constErrors.frag b/Test/constErrors.frag
index df49afcd435848a4f8a5cd97d366e17b5b5e49d1..0067af1180d1974816f6942154992a8c1e73374a 100644
--- a/Test/constErrors.frag
+++ b/Test/constErrors.frag
@@ -31,3 +31,5 @@ const struct S2 {
     ivec2 iv2;
     mat2x4 m;
 } s2 = S2(vec3(3.0), ivec2(3, constInt), mat2x4(1.0, 2.0, 3.0, inVar.x, 5.0, 6.0, 7.0, 8.0));  // ERROR, non-constant matrix
+
+const float f = 3; // okay, type conversion
diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h
index 095ee236339e9724cf70d84fd6c95b7abfd8d13a..93fa11a0f2f61b6630af474fa81ac7ed9e1e28c1 100644
--- a/glslang/Include/BaseTypes.h
+++ b/glslang/Include/BaseTypes.h
@@ -64,7 +64,7 @@ enum TBasicType {
 enum TStorageQualifier {
     EvqTemporary,     // For temporaries (within a function), read/write
     EvqGlobal,        // For globals read/write
-    EvqConst,         // User defined constants and non-output parameters in functions
+    EvqConst,         // User-defined constant values, will be semantically constant and constant folded
     EvqVaryingIn,     // pipeline input, read only
     EvqVaryingOut,    // pipeline ouput, read/write
     EvqUniform,       // read only, shader with app
@@ -74,7 +74,8 @@ enum TStorageQualifier {
     EvqIn,            // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
     EvqOut,           // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
     EvqInOut,
-    EvqConstReadOnly,
+
+    EvqConstReadOnly, // read-only types, not having a constant value or constant-value semantics
 
     // built-ins read by vertex shader
     EvqVertexId,
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 442023aba9d33cab52a1d82af53235ba240e718f..11543804e340bd60cc99575e412daf4c776870a0 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -799,9 +799,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
         // Their parameters will be verified algorithmically.
         //
         TType type(EbtVoid);  // use this to get the type back
-        if (constructorError(loc, intermNode, *fnCall, op, type)) {
-            result = 0;
-        } else {
+        if (! constructorError(loc, intermNode, *fnCall, op, type)) {
             //
             // It's a constructor, of type 'type'.
             //
@@ -809,9 +807,6 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
             if (result == 0)
                 error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
         }
-
-        if (result == 0)
-            result = intermediate.setAggregateOperator(0, op, type, loc);
     } else {
         //
         // Not a constructor.  Find it in the symbol table.
@@ -832,7 +827,6 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
                     error(intermNode->getLoc(), " wrong operand type", "Internal Error",
                                         "built in unary operator function.  Type: %s",
                                         static_cast<TIntermTyped*>(intermNode)->getCompleteString().c_str());
-                    return 0;
                 }
             } else {
                 // This is a function call not mapped to built-in operation
@@ -872,6 +866,14 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
         }
     }
 
+    // generic error recovery
+    // TODO: coding: localize all the error recoveries that look like this
+    if (result == 0) {
+        TConstUnionArray unionArray(1);
+        unionArray[0].setDConst(0.0);
+        result = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), loc);
+    }
+
     return result;
 }
 
@@ -1197,7 +1199,7 @@ bool TParseContext::lValueErrorCheck(TSourceLoc loc, const char* op, TIntermType
 // Both test, and if necessary spit out an error, to see if the node is really
 // a constant.
 //
-void TParseContext::constCheck(TIntermTyped* node, const char* token)
+void TParseContext::constantValueCheck(TIntermTyped* node, const char* token)
 {
     if (node->getQualifier().storage != EvqConst)
         error(node->getLoc(), "constant expression required", token, "");
@@ -1827,9 +1829,10 @@ void TParseContext::updateMaxArraySize(TSourceLoc loc, TIntermNode *node, int in
 void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TType& type)
 {
     //
-    // Make the qualifier make sense.
+    // Make the qualifier make sense, given that there is an initializer.
     //
-    if (type.getQualifier().storage == EvqConst) {
+    if (type.getQualifier().storage == EvqConst || 
+        type.getQualifier().storage == EvqConstReadOnly) {
         type.getQualifier().storage = EvqTemporary;
         error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
     }
@@ -2242,6 +2245,9 @@ TVariable* TParseContext::declareNonArray(TSourceLoc loc, TString& identifier, T
 //
 // Handle all types of initializers from the grammar.
 //
+// Returning 0 just means there is no code to execute to handle the
+// initializer, which will, for example, be the case for constant initalizers.
+//
 TIntermNode* TParseContext::executeInitializer(TSourceLoc loc, TString& identifier,
                                                TIntermTyped* initializer, TVariable* variable)
 {
@@ -2274,37 +2280,43 @@ TIntermNode* TParseContext::executeInitializer(TSourceLoc loc, TString& identifi
         variable->getType().isArray() && variable->getType().getArraySize() == 0)
         variable->getWritableType().changeArraySize(initializer->getType().getArraySize());
 
-    //
-    // test for and propagate constant
-    //
-    if (qualifier == EvqConst || qualifier == EvqUniform) {
+    // Uniform and global consts require a constant initializer
+    if (qualifier == EvqUniform && initializer->getType().getQualifier().storage != EvqConst) {
+        error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+        variable->getWritableType().getQualifier().storage = EvqTemporary;
+        return 0;
+    }
+    if (qualifier == EvqConst && symbolTable.atGlobalLevel() && initializer->getType().getQualifier().storage != EvqConst) {
+        error(loc, "global const initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str());
+        variable->getWritableType().getQualifier().storage = EvqTemporary;
+        return 0;
+    }
+
+    // Const variables require a constant initializer, depending on version
+    if (qualifier == EvqConst) {
         if (initializer->getType().getQualifier().storage != EvqConst) {
-            error(loc, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
-            variable->getWritableType().getQualifier().storage = EvqTemporary;
-            return 0;
+            const char* initFeature = "non-constant initializer";
+            requireProfile(loc, ECoreProfile | ECompatibilityProfile, initFeature);
+            profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shading_language_420pack, initFeature);
+            variable->getWritableType().getQualifier().storage = EvqConstReadOnly;
+            qualifier = EvqConstReadOnly;
         }
-        if (variable->getType() != initializer->getType()) {
-            error(loc, " non-matching types for const initializer ",
-                variable->getType().getStorageQualifierString(), "");
-            variable->getWritableType().getQualifier().storage = EvqTemporary;
-            return 0;
-        }
-        if (initializer->getAsConstantUnion())
-            variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
-        else if (initializer->getAsSymbolNode()) {
-            TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getName());
-            if (const TVariable* tVar = symbol->getAsVariable())
-                variable->setConstArray(tVar->getConstArray());
-            else {
-                error(loc, "expected variable", initializer->getAsSymbolNode()->getName().c_str(), "");
-                return 0;
-            }
-        } else {
-            error(loc, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
+    }
+
+    if (qualifier == EvqConst || qualifier == EvqUniform) {
+        // Compile-time tagging of the variable with it's constant value...
+
+        initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer);
+        if (! initializer || ! initializer->getAsConstantUnion() || variable->getType() != initializer->getType()) {
+            error(loc, "non-matching or non-convertible constant type for const initializer",
+                  variable->getType().getStorageQualifierString(), "");
             variable->getWritableType().getQualifier().storage = EvqTemporary;
             return 0;
         }
+
+        variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
     } else {
+        // normal assigning of a value to a variable...
         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), loc);
         TIntermNode* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
         if (! initNode)
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index 208e5faab6631b5f557459fa53b4fa36d1ea9835..a7de01ac277fa38e8a0d3bab6103a9eefd815215 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -90,7 +90,7 @@ public:
     void binaryOpError(TSourceLoc, const char* op, TString left, TString right);
     void variableCheck(TIntermTyped*& nodePtr);
     bool lValueErrorCheck(TSourceLoc, const char* op, TIntermTyped*);
-    void constCheck(TIntermTyped* node, const char* token);
+    void constantValueCheck(TIntermTyped* node, const char* token);
     void integerCheck(TIntermTyped* node, const char* token);
     void globalCheck(TSourceLoc, const char* token);
     bool constructorError(TSourceLoc, TIntermNode*, TFunction&, TOperator, TType&);
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index c71592571cb8039bbdac8ceb1f85964bdb655a5b..4c4f08c2e23dc2e8ac4709a819bd6cf818fa0940 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -300,8 +300,6 @@ integer_expression
 function_call
     : function_call_or_method {
         $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode, $1.intermAggregate);
-        if ($$ == 0)
-            YYERROR;
         delete $1.function;
     }
     ;
@@ -738,7 +736,7 @@ expression
 
 constant_expression
     : conditional_expression {
-        parseContext.constCheck($1, "");
+        parseContext.constantValueCheck($1, "");
         $$ = $1;
     }
     ;
@@ -1160,7 +1158,7 @@ single_type_qualifier
 storage_qualifier
     : CONST {
         $$.init($1.loc);
-        $$.qualifier.storage = EvqConst;
+        $$.qualifier.storage = EvqConst;  // will later turn into EvqConstReadOnly, if the initializer is not constant
     }
     | ATTRIBUTE {
         parseContext.requireStage($1.loc, EShLangVertex, "attribute");
@@ -2247,7 +2245,7 @@ switch_statement_list
 
 case_label
     : CASE expression COLON {
-        parseContext.constCheck($2, "case");
+        parseContext.constantValueCheck($2, "case");
         parseContext.integerCheck($2, "case");
         $$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc);
     }