diff --git a/Test/330.frag b/Test/330.frag
index 22143f8447b08a8c9aac768a1090aa558a6bfff3..b90ae54e36a3786f01251a4329a76c6e84fe455d 100644
--- a/Test/330.frag
+++ b/Test/330.frag
@@ -39,3 +39,15 @@ in gl_PerVertex {  // ERROR
 in gl_PerVertex {  // ERROR
     vec4 gl_FragCoord;
 };  // ERROR
+
+const int start = 6;
+layout(location = -2) in vec4 v1;         // ERROR
+layout(location = start + 2) in vec4 v2;  // ERROR
+layout(location = 4.7e10) in vec4 v20;    // ERROR
+
+#extension GL_ARB_enhanced_layouts : enable
+
+layout(location = start) in vec4 v3;
+layout(location = -2) in vec4 v4;         // ERROR
+layout(location = -start) in vec4 v5;     // ERROR
+layout(location = start*start - 2) in vec4 v6;
diff --git a/Test/baseResults/330.frag.out b/Test/baseResults/330.frag.out
index cb28b8ebcbdeb57679cb5780aa63cc2e335ed357..0ada0598c21204dddac71feeea88e9fd52b5bf6e 100644
--- a/Test/baseResults/330.frag.out
+++ b/Test/baseResults/330.frag.out
@@ -5,7 +5,14 @@ ERROR: 0:31: 'gl_' : reserved built-in name: gl_name
 ERROR: 0:32: 'gl_' : reserved built-in name: gl_i
 ERROR: 0:35: 'gl_in' : no declaration found for redeclaration 
 ERROR: 0:39: 'gl_FragCoord' : cannot redeclare a non block as a block 
-ERROR: 5 compilation errors.  No code generated.
+ERROR: 0:44: 'non-literal layout-id value' : not supported for this version or the enabled extensions 
+ERROR: 0:44: 'layout-id value' : cannot be negative 
+ERROR: 0:45: 'non-literal layout-id value' : not supported for this version or the enabled extensions 
+ERROR: 0:46: 'layout-id value' : scalar integer expression required 
+ERROR: 0:46: 'location' : location is too large 
+ERROR: 0:51: 'layout-id value' : cannot be negative 
+ERROR: 0:52: 'layout-id value' : cannot be negative 
+ERROR: 12 compilation errors.  No code generated.
 
 
 ERROR: node is still EOpNull!
@@ -45,6 +52,15 @@ ERROR: node is still EOpNull!
 0:?     'varyingVar' (smooth in 4-component vector of float)
 0:?     '__anon__0' (in block{in 4-component vector of float gl_Color, })
 0:?     'gl_name' (in block{in int gl_i})
+0:?     'start' (const int)
+0:?       6 (const int)
+0:?     'v1' (smooth in 4-component vector of float)
+0:?     'v2' (layout(location=8 ) smooth in 4-component vector of float)
+0:?     'v20' (smooth in 4-component vector of float)
+0:?     'v3' (layout(location=6 ) smooth in 4-component vector of float)
+0:?     'v4' (smooth in 4-component vector of float)
+0:?     'v5' (smooth in 4-component vector of float)
+0:?     'v6' (layout(location=34 ) smooth in 4-component vector of float)
 
 
 Linked fragment stage:
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index 6b0570a29400522ea21f86009161813ecb5ff87e..b73083a7696426943f23efc3f95ab13c5bca3291 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -494,15 +494,18 @@ protected:
 
 class TIntermConstantUnion : public TIntermTyped {
 public:
-    TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua) { }
+    TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua), literal(false) { }
     const TConstUnionArray& getConstArray() const { return unionArray; }
     virtual       TIntermConstantUnion* getAsConstantUnion()       { return this; }
     virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
     virtual void traverse(TIntermTraverser*);
     virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
     virtual TIntermTyped* fold(TOperator, const TType&) const;
+    void setLiteral() { literal = true; }
+    bool isLiteral() const { return literal; }
 protected:
     const TConstUnionArray unionArray;
+    bool literal;  // true if node represents a literal in the source code
 };
 
 //
diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h
index a24f55d53e1a6b8a7d9a43bad7ddb60e3046a30f..90a7e2716079047fe6a31a5884e4a5d678514ef2 100644
--- a/glslang/Include/revision.h
+++ b/glslang/Include/revision.h
@@ -9,5 +9,5 @@
 // source have to figure out how to create revision.h just to get a build
 // going.  However, if it is not updated, it can be a version behind.
 
-#define GLSLANG_REVISION "24664"
-#define GLSLANG_DATE     "2014/01/06 14:27:56"
+#define GLSLANG_REVISION "24674"
+#define GLSLANG_DATE     "2014/01/07 10:44:41"
diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp
index 7e045b6b1770c874cd1675e54cd841ae257da115..801cf1d10567cf332744d065c13ba30230c3a5f7 100644
--- a/glslang/MachineIndependent/Constant.cpp
+++ b/glslang/MachineIndependent/Constant.cpp
@@ -85,7 +85,7 @@ namespace glslang {
 //
 // Returns a new node representing the result.
 //
-TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* constantNode) const 
+TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* constantNode) const
 {
     // For most cases, the return type matches the argument type, so set that
     // up and just code to exceptions below.
diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index eaa070eec0295df79f14d43dcc703184f919dff4..952d103e76e8cc4d3cc493ef63853e84e57f2e67 100644
--- a/glslang/MachineIndependent/Intermediate.cpp
+++ b/glslang/MachineIndependent/Intermediate.cpp
@@ -782,10 +782,12 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
 // Returns the constant union node created.
 //
 
-TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, TSourceLoc loc)
+TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, TSourceLoc loc, bool literal)
 {
     TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
     node->setLoc(loc);
+    if (literal)
+        node->setLiteral();
 
     return node;
 }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 00b8b889b36729230794ea21f74446a9980683d8..12cfb59f41fd5549856abd251048cb03084c9bbc 100644
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -2808,12 +2808,24 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
 
 // Put the id's layout qualifier value into the public type.  This is before we know any
 // type information for error checking.
-void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id, int value)
+void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType, TString& id, const TIntermTyped* node)
 {
+    const char* feature = "layout-id value";
+    const char* nonLiteralFeature = "non-literal layout-id value";
+
+    integerCheck(node, feature);
+    const TIntermConstantUnion* constUnion = node->getAsConstantUnion();
+    assert(constUnion);
+    int value = node->getAsConstantUnion()->getConstArray()[0].getIConst();
+
+    if (! constUnion->isLiteral()) {
+        requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature);
+        profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, GL_ARB_enhanced_layouts, nonLiteralFeature);
+    }
+
     if (value < 0) {
-        error(loc, "cannot be negative", "layout qualifier value", "");
+        error(loc, "cannot be negative", feature, "");
         return;
-        // TODO: 4.4: test the above, once expressions are allowed; until then, can't even express a negative location
     }
 
     std::transform(id.begin(), id.end(), id.begin(), ::tolower);
diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h
index b8c790639c72b0929097204d343ffa6dd396b39d..a2dcc605efe889756cc490fbadefbf45261d4b9c 100644
--- a/glslang/MachineIndependent/ParseHelper.h
+++ b/glslang/MachineIndependent/ParseHelper.h
@@ -148,7 +148,7 @@ public:
     void constantIndexExpressionCheck(TIntermNode*);
 
     void setLayoutQualifier(TSourceLoc, TPublicType&, TString&);
-    void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int);
+    void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, const TIntermTyped*);
     void mergeObjectLayoutQualifiers(TSourceLoc, TQualifier& dest, const TQualifier& src, bool inheritOnly);
     void layoutTypeCheck(TSourceLoc, const TSymbol&);
     void layoutQualifierCheck(TSourceLoc, const TQualifier&);
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 6fc97f744de0b66372282a0e2e2e04f1f86ddb94..5fe2de3852d87e8aaa15cb661329d44017e44992 100644
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -162,6 +162,7 @@ void TParseContext::initializeExtensionBehavior()
     extensionBehavior[GL_ARB_gpu_shader5]              = EBhDisablePartial;
     extensionBehavior[GL_ARB_separate_shader_objects]  = EBhDisable;
     extensionBehavior[GL_ARB_tessellation_shader]      = EBhDisable;
+    extensionBehavior[GL_ARB_enhanced_layouts]         = EBhDisable;
 }
 
 // Get code that is not part of a shared symbol table, is specific to this shader,
@@ -184,7 +185,8 @@ const char* TParseContext::getPreamble()
             "#define GL_ARB_texture_gather 1\n"
             "#define GL_ARB_gpu_shader5 1\n"
             "#define GL_ARB_separate_shader_objects 1\n"
-            "#define GL_ARB_tessellation_shader 1\n";
+            "#define GL_ARB_tessellation_shader 1\n"
+            "#define GL_ARB_enhanced_layouts 1\n";
     }
 }
 
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index d0997b816f569641e000fb6eb142899b547fc661..e7ccd2e6813cca34c1c29f095621888a4a55aab3 100644
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -86,6 +86,7 @@ const char* const GL_ARB_texture_gather           = "GL_ARB_texture_gather";
 const char* const GL_ARB_gpu_shader5              = "GL_ARB_gpu_shader5";
 const char* const GL_ARB_separate_shader_objects  = "GL_ARB_separate_shader_objects";
 const char* const GL_ARB_tessellation_shader      = "GL_ARB_tessellation_shader";
+const char* const GL_ARB_enhanced_layouts         = "GL_ARB_enhanced_layouts";
 
 } // end namespace glslang
 
diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y
index a1dda8723af73765125f4b8aab07dff17f3ed87c..11d603859c5edf16042240827d274badbb6a0993 100644
--- a/glslang/MachineIndependent/glslang.y
+++ b/glslang/MachineIndependent/glslang.y
@@ -228,29 +228,29 @@ primary_expression
     | INTCONSTANT {
         TConstUnionArray unionArray(1);
         unionArray[0].setIConst($1.i);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.loc, true);
     }
     | UINTCONSTANT {        
         parseContext.fullIntegerCheck($1.loc, "unsigned literal");
         TConstUnionArray unionArray(1);
         unionArray[0].setUConst($1.u);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), $1.loc, true);
     }
     | FLOATCONSTANT {
         TConstUnionArray unionArray(1);
         unionArray[0].setDConst($1.d);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.loc, true);
     }
     | DOUBLECONSTANT {
         parseContext.doubleCheck($1.loc, "double literal");
         TConstUnionArray unionArray(1);
         unionArray[0].setDConst($1.d);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtDouble, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtDouble, EvqConst), $1.loc, true);
     }
     | BOOLCONSTANT {
         TConstUnionArray unionArray(1);
         unionArray[0].setBConst($1.b);
-        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.loc);
+        $$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.loc, true);
     }
     | LEFT_PAREN expression RIGHT_PAREN {
         $$ = $2;
@@ -1110,13 +1110,9 @@ layout_qualifier_id
         $$.init($1.loc);
         parseContext.setLayoutQualifier($1.loc, $$, *$1.string);
     }
-    | IDENTIFIER EQUAL INTCONSTANT {
+    | IDENTIFIER EQUAL constant_expression {
         $$.init($1.loc);
-        parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3.i);
-    }
-    | IDENTIFIER EQUAL UINTCONSTANT {
-        $$.init($1.loc);
-        parseContext.setLayoutQualifier($1.loc, $$, *$1.string, (int)$3.u);
+        parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3);
     }
     | SHARED { // because "shared" is both an identifier and a keyword
         $$.init($1.loc);
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 2ce1f1fdc89ebbaa1cb6662ca92003a4c45b8070..eb85dafa22b516cc848c546ff3028e980400396f 100644
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -96,7 +96,7 @@ public:
     TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
     TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
-    TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc);
+    TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc, bool literal = false);
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
     bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
     TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);