aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Kessenich <cepheus@frii.com>2013-10-17 20:55:30 +0000
committerJohn Kessenich <cepheus@frii.com>2013-10-17 20:55:30 +0000
commite46b087760ed2b4eb0805302d9f314f612282de5 (patch)
tree040f812c832113a1ddebf2ffc1d1d743ba2e59d3
parent779e6b406a3962258d744986fdda944f03cbb85d (diff)
downloadglslang-e46b087760ed2b4eb0805302d9f314f612282de5.tar.gz
Add function "const", where the initializer does not have to be a compile-time constant.
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23566 e7fa87d3-cd2b-0410-9028-fcbf551c1848
-rw-r--r--Test/420.vert17
-rw-r--r--Test/baseResults/120.vert.out12
-rw-r--r--Test/baseResults/420.tese.out7
-rw-r--r--Test/baseResults/420.vert.out83
-rw-r--r--Test/baseResults/array.frag.out2
-rw-r--r--Test/baseResults/constErrors.frag.out13
-rw-r--r--Test/baseResults/matrixError.vert.out2
-rw-r--r--Test/baseResults/specExamples.frag.out19
-rw-r--r--Test/baseResults/specExamples.vert.out12
-rw-r--r--Test/baseResults/uint.frag.out8
-rw-r--r--Test/constErrors.frag2
-rw-r--r--glslang/Include/BaseTypes.h5
-rw-r--r--glslang/MachineIndependent/ParseHelper.cpp82
-rw-r--r--glslang/MachineIndependent/ParseHelper.h2
-rw-r--r--glslang/MachineIndependent/glslang.y8
15 files changed, 164 insertions, 110 deletions
diff --git a/Test/420.vert b/Test/420.vert
index 3f4fa699..04dd1709 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 bb956dea..9f499f87 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 415129bf..2b5af43d 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 6703561a..4201808d 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 b87a9bf0..36401844 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 bd249e2f..48ec2499 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 65f623e4..fa5a82bd 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 9eb9566b..a0e46f84 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 5edf37f6..c06df108 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 2a14b8ad..428df239 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 df49afcd..0067af11 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 095ee236..93fa11a0 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 442023ab..11543804 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 208e5faa..a7de01ac 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 c7159257..4c4f08c2 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);
}