зеркало из https://github.com/stride3d/xkslang.git
Flesh out 4.x block redeclaration semantics:
- hide non-redeclared anonymous members - array size limit checking - illegal member qualifiers - additional members git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@24406 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
Родитель
e1b2e39a56
Коммит
c719481d43
|
@ -23,3 +23,19 @@ void foo()
|
||||||
vec4 c = gl_Color;
|
vec4 c = gl_Color;
|
||||||
outVar = inVar;
|
outVar = inVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
in gl_block { // ERROR
|
||||||
|
int gl_i;
|
||||||
|
} gl_name;
|
||||||
|
|
||||||
|
in myBlock {
|
||||||
|
int gl_i; // ERROR
|
||||||
|
} gl_name; // ERROR
|
||||||
|
|
||||||
|
in gl_PerVertex { // ERROR
|
||||||
|
vec4 gl_FragCoord;
|
||||||
|
} gl_in[];
|
||||||
|
|
||||||
|
in gl_PerVertex { // ERROR
|
||||||
|
vec4 gl_FragCoord;
|
||||||
|
}; // ERROR
|
||||||
|
|
|
@ -17,6 +17,7 @@ layout(max_vertices = 127, invocations = 4) out;
|
||||||
|
|
||||||
in gl_PerVertex { // testing input arrays with a block redeclaration, see 420.geom for without
|
in gl_PerVertex { // testing input arrays with a block redeclaration, see 420.geom for without
|
||||||
vec4 gl_Position;
|
vec4 gl_Position;
|
||||||
|
layout(std140, location = 3) patch float gl_PointSize; // ERRORs...
|
||||||
} gl_in[];
|
} gl_in[];
|
||||||
|
|
||||||
void foo()
|
void foo()
|
||||||
|
|
|
@ -29,4 +29,6 @@ void foo()
|
||||||
{
|
{
|
||||||
float p = gl_in[1].gl_PointSize; // use of redeclared
|
float p = gl_in[1].gl_PointSize; // use of redeclared
|
||||||
gl_PointSize = p; // use of redeclared
|
gl_PointSize = p; // use of redeclared
|
||||||
|
vec4 v = gl_in[1].gl_Position; // ERROR, not included in the redeclaration
|
||||||
|
gl_Position = vec4(1.0); // ERROR, not included in the redeclaration
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,3 +43,8 @@ void foo4()
|
||||||
v4.x = 3.2; // ERROR
|
v4.x = 3.2; // ERROR
|
||||||
v4.xy; // should have non-uniform type
|
v4.xy; // should have non-uniform type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out gl_PerVertex {
|
||||||
|
float gl_PointSize[1]; // ERROR, adding array
|
||||||
|
float gl_ClipDistance; // ERROR, removing array
|
||||||
|
};
|
||||||
|
|
|
@ -77,3 +77,7 @@ layout(binding = 31) uniform sampler2D sampb5[2]; // ERROR, binding too big
|
||||||
|
|
||||||
int fgfg(float f, mediump int i);
|
int fgfg(float f, mediump int i);
|
||||||
int fgfg(float f, highp int i);
|
int fgfg(float f, highp int i);
|
||||||
|
|
||||||
|
out gl_PerVertex {
|
||||||
|
float gl_ClipDistance[4];
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
330.frag
|
330.frag
|
||||||
Warning, version 330 is not yet complete; some version-specific features are present, but many are missing.
|
Warning, version 330 is not yet complete; some version-specific features are present, but many are missing.
|
||||||
|
ERROR: 0:27: 'block declaration' : cannot redeclare block: gl_block
|
||||||
|
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.
|
||||||
|
|
||||||
0:? Sequence
|
|
||||||
|
ERROR: node is still EOpNull!
|
||||||
0:8 Function Definition: main( (void)
|
0:8 Function Definition: main( (void)
|
||||||
0:8 Function Parameters:
|
0:8 Function Parameters:
|
||||||
0:10 Sequence
|
0:10 Sequence
|
||||||
|
@ -26,9 +33,9 @@ Warning, version 330 is not yet complete; some version-specific features are pre
|
||||||
0:23 move second child to first child (4-component vector of float)
|
0:23 move second child to first child (4-component vector of float)
|
||||||
0:23 'c' (4-component vector of float)
|
0:23 'c' (4-component vector of float)
|
||||||
0:23 gl_Color: direct index for structure (in 4-component vector of float)
|
0:23 gl_Color: direct index for structure (in 4-component vector of float)
|
||||||
0:23 '__anon__0' (in block{gl_Color})
|
0:23 '__anon__0' (in block{gl_Color,})
|
||||||
0:23 Constant:
|
0:23 Constant:
|
||||||
0:23 0 (const uint)
|
0:23 2 (const uint)
|
||||||
0:24 move second child to first child (4-component vector of float)
|
0:24 move second child to first child (4-component vector of float)
|
||||||
0:24 'outVar' (out 4-component vector of float)
|
0:24 'outVar' (out 4-component vector of float)
|
||||||
0:24 'inVar' (smooth in 4-component vector of float)
|
0:24 'inVar' (smooth in 4-component vector of float)
|
||||||
|
@ -36,7 +43,8 @@ Warning, version 330 is not yet complete; some version-specific features are pre
|
||||||
0:? 'inVar' (smooth in 4-component vector of float)
|
0:? 'inVar' (smooth in 4-component vector of float)
|
||||||
0:? 'outVar' (out 4-component vector of float)
|
0:? 'outVar' (out 4-component vector of float)
|
||||||
0:? 'varyingVar' (smooth in 4-component vector of float)
|
0:? 'varyingVar' (smooth in 4-component vector of float)
|
||||||
0:? '__anon__0' (in block{gl_Color})
|
0:? '__anon__0' (in block{gl_Color,})
|
||||||
|
0:? 'gl_name' (in block{gl_i})
|
||||||
|
|
||||||
|
|
||||||
Linked fragment stage:
|
Linked fragment stage:
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
400.geom
|
400.geom
|
||||||
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
|
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
|
||||||
ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier
|
ERROR: 0:13: 'invocations' : can only apply to a standalone qualifier
|
||||||
ERROR: 0:24: 'length' : array must be declared with a size before using this method
|
ERROR: 0:20: 'gl_PointSize' : cannot add layout to redeclared block member
|
||||||
ERROR: 0:35: 'length' : array must be declared with a size before using this method
|
ERROR: 0:20: 'gl_PointSize' : cannot add patch to redeclared block member
|
||||||
ERROR: 0:39: 'triangles' : inconsistent input primitive for array size colorBad
|
ERROR: 0:25: 'length' : array must be declared with a size before using this method
|
||||||
ERROR: 0:43: 'triangles' : inconsistent input primitive for array size colorbad2
|
ERROR: 0:36: 'length' : array must be declared with a size before using this method
|
||||||
ERROR: 0:55: 'location' : repeated use of location 4
|
ERROR: 0:40: 'triangles' : inconsistent input primitive for array size colorBad
|
||||||
ERROR: 6 compilation errors. No code generated.
|
ERROR: 0:44: 'triangles' : inconsistent input primitive for array size colorbad2
|
||||||
|
ERROR: 0:56: 'location' : repeated use of location 4
|
||||||
|
ERROR: 8 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
invocations = 4
|
invocations = 4
|
||||||
|
@ -29,39 +31,39 @@ ERROR: node is still EOpNull!
|
||||||
0:10 move second child to first child (int)
|
0:10 move second child to first child (int)
|
||||||
0:10 'id' (int)
|
0:10 'id' (int)
|
||||||
0:10 'gl_InvocationID' (in int)
|
0:10 'gl_InvocationID' (in int)
|
||||||
0:22 Function Definition: foo( (void)
|
0:23 Function Definition: foo( (void)
|
||||||
0:22 Function Parameters:
|
0:23 Function Parameters:
|
||||||
0:24 Sequence
|
0:25 Sequence
|
||||||
0:24 Constant:
|
|
||||||
0:24 1 (const int)
|
|
||||||
0:25 gl_Position: direct index for structure (4-component vector of float)
|
|
||||||
0:25 direct index (block{gl_Position})
|
|
||||||
0:25 'gl_in' (in 3-element array of block{gl_Position})
|
|
||||||
0:25 Constant:
|
0:25 Constant:
|
||||||
0:25 1 (const int)
|
0:25 1 (const int)
|
||||||
0:25 Constant:
|
0:26 gl_Position: direct index for structure (4-component vector of float)
|
||||||
0:25 0 (const int)
|
0:26 direct index (block{gl_Position,gl_PointSize})
|
||||||
0:33 Function Definition: foo2( (void)
|
0:26 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize})
|
||||||
0:33 Function Parameters:
|
0:26 Constant:
|
||||||
0:35 Sequence
|
0:26 1 (const int)
|
||||||
0:35 Constant:
|
0:26 Constant:
|
||||||
0:35 1 (const int)
|
0:26 0 (const int)
|
||||||
|
0:34 Function Definition: foo2( (void)
|
||||||
|
0:34 Function Parameters:
|
||||||
|
0:36 Sequence
|
||||||
0:36 Constant:
|
0:36 Constant:
|
||||||
0:36 3 (const int)
|
0:36 1 (const int)
|
||||||
0:45 Function Definition: foo3( (void)
|
0:37 Constant:
|
||||||
0:45 Function Parameters:
|
0:37 3 (const int)
|
||||||
0:47 Sequence
|
0:46 Function Definition: foo3( (void)
|
||||||
0:47 Constant:
|
0:46 Function Parameters:
|
||||||
0:47 3 (const int)
|
0:48 Sequence
|
||||||
0:48 Constant:
|
0:48 Constant:
|
||||||
0:48 3 (const int)
|
0:48 3 (const int)
|
||||||
0:49 Constant:
|
0:49 Constant:
|
||||||
0:49 3 (const int)
|
0:49 3 (const int)
|
||||||
0:50 Constant:
|
0:50 Constant:
|
||||||
0:50 3 (const int)
|
0:50 3 (const int)
|
||||||
|
0:51 Constant:
|
||||||
|
0:51 3 (const int)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? '__anon__0' (layout(stream=0 ) out block{a})
|
0:? '__anon__0' (layout(stream=0 ) out block{a})
|
||||||
0:? 'gl_in' (in 3-element array of block{gl_Position})
|
0:? 'gl_in' (in 3-element array of block{gl_Position,gl_PointSize})
|
||||||
0:? 'color' (in 3-element array of 4-component vector of float)
|
0:? 'color' (in 3-element array of 4-component vector of float)
|
||||||
0:? 'color2' (in 3-element array of 4-component vector of float)
|
0:? 'color2' (in 3-element array of 4-component vector of float)
|
||||||
0:? 'colorS' (in 3-element array of 4-component vector of float)
|
0:? 'colorS' (in 3-element array of 4-component vector of float)
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
410.geom
|
410.geom
|
||||||
Warning, version 410 is not yet complete; some version-specific features are present, but many are missing.
|
Warning, version 410 is not yet complete; some version-specific features are present, but many are missing.
|
||||||
ERROR: 0:8: 'myIn' : cannot redeclare a built-in block with a user name
|
ERROR: 0:8: 'myIn' : cannot redeclare a built-in block with a user name
|
||||||
ERROR: 0:8: 'gl_' : reserved built-in name
|
ERROR: 0:12: 'gl_myIn' : no declaration found for redeclaration
|
||||||
ERROR: 0:12: 'gl_' : reserved built-in name
|
|
||||||
ERROR: 0:20: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use
|
ERROR: 0:20: 'gl_PerVertex' : can only redeclare a built-in block once, and before any use
|
||||||
ERROR: 0:20: 'gl_' : reserved built-in name
|
ERROR: 0:32: 'gl_Position' : no such field in structure
|
||||||
ERROR: 5 compilation errors. No code generated.
|
ERROR: 0:32: '=' : cannot convert from 'block{gl_PointSize}' to '4-component vector of float'
|
||||||
|
ERROR: 0:33: 'gl_Position' : member of nameless block was not redeclared
|
||||||
|
ERROR: 0:33: 'assign' : cannot convert from 'const 4-component vector of float' to 'layout(stream=0 ) gl_Position void'
|
||||||
|
ERROR: 7 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
invocations = 0
|
invocations = 0
|
||||||
|
@ -35,13 +37,17 @@ ERROR: node is still EOpNull!
|
||||||
0:30 0 (const int)
|
0:30 0 (const int)
|
||||||
0:31 move second child to first child (float)
|
0:31 move second child to first child (float)
|
||||||
0:31 gl_PointSize: direct index for structure (layout(stream=0 ) gl_PointSize float)
|
0:31 gl_PointSize: direct index for structure (layout(stream=0 ) gl_PointSize float)
|
||||||
0:31 '__anon__0' (layout(stream=0 ) out block{gl_PointSize})
|
0:31 '__anon__0' (layout(stream=0 ) out block{gl_PointSize,})
|
||||||
0:31 Constant:
|
0:31 Constant:
|
||||||
0:31 0 (const uint)
|
0:31 1 (const uint)
|
||||||
0:31 'p' (float)
|
0:31 'p' (float)
|
||||||
|
0:33 gl_Position: direct index for structure (layout(stream=0 ) gl_Position void)
|
||||||
|
0:33 '__anon__0' (layout(stream=0 ) out block{gl_PointSize,})
|
||||||
|
0:33 Constant:
|
||||||
|
0:33 0 (const uint)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'gl_in' (in unsized array of block{gl_PointSize})
|
0:? 'gl_in' (in unsized array of block{gl_PointSize})
|
||||||
0:? '__anon__0' (layout(stream=0 ) out block{gl_PointSize})
|
0:? '__anon__0' (layout(stream=0 ) out block{gl_PointSize,})
|
||||||
|
|
||||||
|
|
||||||
Linked geometry stage:
|
Linked geometry stage:
|
||||||
|
|
|
@ -4,7 +4,9 @@ ERROR: 0:9: 'length' : array must be declared with a size before using this met
|
||||||
ERROR: 0:11: '[' : array must be redeclared with a size before being indexed with a variable
|
ERROR: 0:11: '[' : array must be redeclared with a size before being indexed with a variable
|
||||||
ERROR: 0:42: 'assign' : l-value required (can't modify a const)
|
ERROR: 0:42: 'assign' : l-value required (can't modify a const)
|
||||||
ERROR: 0:43: 'assign' : l-value required "v4" (can't modify a uniform)
|
ERROR: 0:43: 'assign' : l-value required "v4" (can't modify a uniform)
|
||||||
ERROR: 4 compilation errors. No code generated.
|
ERROR: 0:48: 'gl_PointSize' : cannot change arrayness of redeclared block member
|
||||||
|
ERROR: 0:49: 'gl_ClipDistance' : cannot change arrayness of redeclared block member
|
||||||
|
ERROR: 6 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
invocations = 0
|
invocations = 0
|
||||||
|
@ -115,6 +117,7 @@ ERROR: node is still EOpNull!
|
||||||
0:? 's2D' (uniform sampler2D)
|
0:? 's2D' (uniform sampler2D)
|
||||||
0:? 'coord' (in 2-component vector of float)
|
0:? 'coord' (in 2-component vector of float)
|
||||||
0:? 'v4' (uniform 4-component vector of float)
|
0:? 'v4' (uniform 4-component vector of float)
|
||||||
|
0:? '__anon__0' (layout(stream=0 ) out block{gl_PointSize,gl_ClipDistance})
|
||||||
|
|
||||||
|
|
||||||
Linked geometry stage:
|
Linked geometry stage:
|
||||||
|
|
|
@ -130,6 +130,7 @@ ERROR: node is still EOpNull!
|
||||||
0:? 'sampb3' (layout(binding=32 ) uniform sampler2D)
|
0:? 'sampb3' (layout(binding=32 ) uniform sampler2D)
|
||||||
0:? 'sampb4' (layout(binding=31 ) uniform sampler2D)
|
0:? 'sampb4' (layout(binding=31 ) uniform sampler2D)
|
||||||
0:? 'sampb5' (layout(binding=31 ) uniform 2-element array of sampler2D)
|
0:? 'sampb5' (layout(binding=31 ) uniform 2-element array of sampler2D)
|
||||||
|
0:? '__anon__3' (out block{gl_ClipDistance,})
|
||||||
0:? 'gl_VertexID' (gl_VertexId int)
|
0:? 'gl_VertexID' (gl_VertexId int)
|
||||||
0:? 'gl_InstanceID' (gl_InstanceId int)
|
0:? 'gl_InstanceID' (gl_InstanceId int)
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@ ERROR: node is still EOpNull!
|
||||||
0:16 move second child to first child (float)
|
0:16 move second child to first child (float)
|
||||||
0:16 direct index (float)
|
0:16 direct index (float)
|
||||||
0:16 gl_ClipDistance: direct index for structure (17-element array of float)
|
0:16 gl_ClipDistance: direct index for structure (17-element array of float)
|
||||||
0:16 '__anon__0' (out block{gl_ClipDistance})
|
0:16 '__anon__0' (out block{gl_ClipDistance,})
|
||||||
0:16 Constant:
|
0:16 Constant:
|
||||||
0:16 0 (const uint)
|
0:16 2 (const uint)
|
||||||
0:16 Constant:
|
0:16 Constant:
|
||||||
0:16 2 (const int)
|
0:16 2 (const int)
|
||||||
0:16 Constant:
|
0:16 Constant:
|
||||||
|
@ -41,7 +41,7 @@ ERROR: node is still EOpNull!
|
||||||
0:? 'uv4' (layout(location=4 ) uniform 4-component vector of float)
|
0:? 'uv4' (layout(location=4 ) uniform 4-component vector of float)
|
||||||
0:? 'b1' (layout(location=2 ) in block{v})
|
0:? 'b1' (layout(location=2 ) in block{v})
|
||||||
0:? 'b2' (layout(location=2 ) out block{v})
|
0:? 'b2' (layout(location=2 ) out block{v})
|
||||||
0:? '__anon__0' (out block{gl_ClipDistance})
|
0:? '__anon__0' (out block{gl_ClipDistance,})
|
||||||
0:? 'cs' (layout(location=10 ) smooth out 2-element array of structure{m,f})
|
0:? 'cs' (layout(location=10 ) smooth out 2-element array of structure{m,f})
|
||||||
0:? 'cf' (layout(location=54 ) smooth out float)
|
0:? 'cf' (layout(location=54 ) smooth out float)
|
||||||
0:? 'cg' (layout(location=53 ) smooth out float)
|
0:? 'cg' (layout(location=53 ) smooth out float)
|
||||||
|
|
|
@ -8,15 +8,15 @@ ERROR: 0:22: 'vn8' : illegal use of type 'void'
|
||||||
ERROR: 0:22: 'vp' : illegal use of type 'void'
|
ERROR: 0:22: 'vp' : illegal use of type 'void'
|
||||||
ERROR: 0:25: 'cij' : variables with qualifier 'const' must be initialized
|
ERROR: 0:25: 'cij' : variables with qualifier 'const' must be initialized
|
||||||
ERROR: 0:27: 'cip' : variables with qualifier 'const' must be initialized
|
ERROR: 0:27: 'cip' : variables with qualifier 'const' must be initialized
|
||||||
ERROR: 0:34: 'gl_' : reserved built-in name
|
ERROR: 0:34: 'gl_' : reserved built-in name: gl_vi4
|
||||||
ERROR: 0:35: 'gl_' : reserved built-in name
|
ERROR: 0:35: 'gl_' : reserved built-in name: gl_vj
|
||||||
ERROR: 0:35: 'gl_' : reserved built-in name
|
ERROR: 0:35: 'gl_' : reserved built-in name: gl_vk5
|
||||||
ERROR: 0:36: 'gl_' : reserved built-in name
|
ERROR: 0:36: 'gl_' : reserved built-in name: gl_vm2
|
||||||
ERROR: 0:36: 'gl_' : reserved built-in name
|
ERROR: 0:36: 'gl_' : reserved built-in name: gl_vm3
|
||||||
ERROR: 0:37: 'gl_' : reserved built-in name
|
ERROR: 0:37: 'gl_' : reserved built-in name: gl_vn8
|
||||||
ERROR: 0:37: 'gl_' : reserved built-in name
|
ERROR: 0:37: 'gl_' : reserved built-in name: gl_vp
|
||||||
ERROR: 0:42: '' : boolean expression expected
|
ERROR: 0:42: '' : boolean expression expected
|
||||||
ERROR: 0:43: 'gl_' : reserved built-in name
|
ERROR: 0:43: 'gl_' : reserved built-in name: gl_cond
|
||||||
ERROR: 18 compilation errors. No code generated.
|
ERROR: 18 compilation errors. No code generated.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -828,10 +828,12 @@ public:
|
||||||
if (structure) {
|
if (structure) {
|
||||||
s.append("{");
|
s.append("{");
|
||||||
for (size_t i = 0; i < structure->size(); ++i) {
|
for (size_t i = 0; i < structure->size(); ++i) {
|
||||||
|
if ((*structure)[i].type->getBasicType() != EbtVoid) {
|
||||||
s.append((*structure)[i].type->getFieldName());
|
s.append((*structure)[i].type->getFieldName());
|
||||||
if (i < structure->size() - 1)
|
if (i < structure->size() - 1)
|
||||||
s.append(",");
|
s.append(",");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
s.append("}");
|
s.append("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,5 +9,5 @@
|
||||||
// source have to figure out how to create revision.h just to get a build
|
// 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.
|
// going. However, if it is not updated, it can be a version behind.
|
||||||
|
|
||||||
#define GLSLANG_REVISION "24397"
|
#define GLSLANG_REVISION "24400"
|
||||||
#define GLSLANG_DATE "2013/12/06 16:57:42"
|
#define GLSLANG_DATE "2013/12/06 17:28:07"
|
||||||
|
|
|
@ -376,6 +376,8 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt
|
||||||
|
|
||||||
node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc);
|
node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc);
|
||||||
node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);
|
node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type);
|
||||||
|
if (node->getBasicType() == EbtVoid)
|
||||||
|
error(loc, "member of nameless block was not redeclared", string->c_str(), "");
|
||||||
if (variable->getType().getQualifier().isIo())
|
if (variable->getType().getQualifier().isIo())
|
||||||
noteAccess = true;
|
noteAccess = true;
|
||||||
|
|
||||||
|
@ -1375,24 +1377,16 @@ void TParseContext::globalCheck(TSourceLoc loc, const char* token)
|
||||||
// Except, if the symbol table is at a built-in level,
|
// Except, if the symbol table is at a built-in level,
|
||||||
// which is when we are parsing built-ins.
|
// which is when we are parsing built-ins.
|
||||||
//
|
//
|
||||||
bool TParseContext::reservedErrorCheck(TSourceLoc loc, const TString& identifier)
|
void TParseContext::reservedErrorCheck(TSourceLoc loc, const TString& identifier)
|
||||||
{
|
{
|
||||||
if (! symbolTable.atBuiltInLevel()) {
|
if (! symbolTable.atBuiltInLevel()) {
|
||||||
if (builtInName(identifier)) {
|
if (builtInName(identifier))
|
||||||
error(loc, "reserved built-in name", "gl_", "");
|
error(loc, "reserved built-in name:", "gl_", identifier.c_str());
|
||||||
|
if (identifier.find("__") != TString::npos)
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (identifier.find("__") != TString::npos) {
|
|
||||||
error(loc, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
|
error(loc, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Reserved errors for the preprocessor.
|
// Reserved errors for the preprocessor.
|
||||||
//
|
//
|
||||||
|
@ -1992,10 +1986,7 @@ void TParseContext::declareArray(TSourceLoc loc, TString& identifier, const TTyp
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (identifier.compare("gl_TexCoord") == 0)
|
arrayLimitCheck(loc, identifier, type.getArraySize());
|
||||||
limitCheck(loc, type.getArraySize(), "gl_MaxTextureCoords", "gl_TexCoord array size");
|
|
||||||
else if (identifier.compare("gl_ClipDistance") == 0)
|
|
||||||
limitCheck(loc, type.getArraySize(), "gl_MaxClipDistances", "gl_ClipDistance array size");
|
|
||||||
|
|
||||||
newType.shareArraySizes(type);
|
newType.shareArraySizes(type);
|
||||||
|
|
||||||
|
@ -2164,24 +2155,27 @@ TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString&
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
|
//
|
||||||
|
// Either redeclare the requested block, or give an error message why it can't be done.
|
||||||
|
//
|
||||||
|
void TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& newTypeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
|
||||||
{
|
{
|
||||||
// just a quick out, not everything that must be checked:
|
const char* feature = "built-in block redeclaration";
|
||||||
if (symbolTable.atBuiltInLevel() || profile == EEsProfile || ! builtInName(blockName))
|
requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature);
|
||||||
return false;
|
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, feature);
|
||||||
|
|
||||||
|
if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment") {
|
||||||
|
error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redeclaring a built-in block...
|
||||||
|
|
||||||
if (instanceName && ! builtInName(*instanceName)) {
|
if (instanceName && ! builtInName(*instanceName)) {
|
||||||
error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
|
error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, "built-in block redeclaration");
|
|
||||||
|
|
||||||
// Potentially redeclaring a built-in block...
|
|
||||||
|
|
||||||
if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Blocks with instance names are easy to find, lookup the instance name,
|
// Blocks with instance names are easy to find, lookup the instance name,
|
||||||
// Anonymous blocks need to be found via a member.
|
// Anonymous blocks need to be found via a member.
|
||||||
bool builtIn;
|
bool builtIn;
|
||||||
|
@ -2189,64 +2183,110 @@ bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, c
|
||||||
if (instanceName)
|
if (instanceName)
|
||||||
block = symbolTable.find(*instanceName, &builtIn);
|
block = symbolTable.find(*instanceName, &builtIn);
|
||||||
else
|
else
|
||||||
block = symbolTable.find(typeList.front().type->getFieldName(), &builtIn);
|
block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn);
|
||||||
|
|
||||||
// If the block was not found, this must be a version/profile/stage
|
// If the block was not found, this must be a version/profile/stage
|
||||||
// that doesn't have it.
|
// that doesn't have it, or the instance name is wrong.
|
||||||
if (! block)
|
const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str();
|
||||||
return false;
|
if (! block) {
|
||||||
|
error(loc, "no declaration found for redeclaration", errorName, "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Built-in blocks cannot be redeclared more than once, which if happened,
|
// Built-in blocks cannot be redeclared more than once, which if happened,
|
||||||
// we'd be finding the already redeclared one here, rather than the built in.
|
// we'd be finding the already redeclared one here, rather than the built in.
|
||||||
if (! builtIn) {
|
if (! builtIn) {
|
||||||
error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), "");
|
error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), "");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the block to make a writable version, to insert into the block table after editing.
|
// Copy the block to make a writable version, to insert into the block table after editing.
|
||||||
block = symbolTable.copyUpDeferredInsert(block);
|
block = symbolTable.copyUpDeferredInsert(block);
|
||||||
|
|
||||||
if (block->getType().getBasicType() != EbtBlock) {
|
if (block->getType().getBasicType() != EbtBlock) {
|
||||||
error(loc, "cannot redeclare a non block as a block", blockName.c_str(), "");
|
error(loc, "cannot redeclare a non block as a block", errorName, "");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
|
// Handle geometry shader input arrays: see inputArrayNodeResizeList comment in ParseHelper.h
|
||||||
if (language == EShLangGeometry && block->getType().isArray() && block->getType().getQualifier().storage == EvqVaryingIn)
|
if (language == EShLangGeometry && block->getType().isArray() && block->getType().getQualifier().storage == EvqVaryingIn)
|
||||||
inputArraySymbolResizeList.push_back(block);
|
inputArraySymbolResizeList.push_back(block);
|
||||||
|
|
||||||
// TODO: SSO/4.10 semantics: block redeclaration: instance array size matching
|
|
||||||
|
|
||||||
// Edit and error check the container against the redeclaration
|
// Edit and error check the container against the redeclaration
|
||||||
// - remove unused members
|
// - remove unused members
|
||||||
// - ensure remaining qualifiers match
|
// - ensure remaining qualifiers/types match
|
||||||
TType& type = block->getWritableType();
|
TType& type = block->getWritableType();
|
||||||
TTypeList::iterator member = type.getStruct()->begin();
|
TTypeList::iterator member = type.getStruct()->begin();
|
||||||
|
size_t numOriginalMembersFound = 0;
|
||||||
while (member != type.getStruct()->end()) {
|
while (member != type.getStruct()->end()) {
|
||||||
// look for match
|
// look for match
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (TTypeList::iterator newMember = typeList.begin(); newMember != typeList.end(); ++newMember) {
|
TTypeList::iterator newMember;
|
||||||
|
TSourceLoc memberLoc;
|
||||||
|
for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) {
|
||||||
if (member->type->getFieldName() == newMember->type->getFieldName()) {
|
if (member->type->getFieldName() == newMember->type->getFieldName()) {
|
||||||
found = true;
|
found = true;
|
||||||
|
memberLoc = newMember->loc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove non-redeclared members
|
if (found) {
|
||||||
if (found)
|
++numOriginalMembersFound;
|
||||||
++member;
|
// - ensure match between redeclared members' types
|
||||||
else
|
// - check for things that can't be changed
|
||||||
member = type.getStruct()->erase(member);
|
// - update things that can be changed
|
||||||
|
TType& oldType = *member->type;
|
||||||
|
const TType& newType = *newMember->type;
|
||||||
|
if (! newType.sameElementType(oldType))
|
||||||
|
error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), "");
|
||||||
|
if (oldType.isArray() != newType.isArray())
|
||||||
|
error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), "");
|
||||||
|
else if (! oldType.sameArrayness(newType) && oldType.getArraySize() > 0)
|
||||||
|
error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), "");
|
||||||
|
else if (newType.isArray())
|
||||||
|
arrayLimitCheck(loc, member->type->getFieldName(), newType.getArraySize());
|
||||||
|
if (newType.getQualifier().isMemory())
|
||||||
|
error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), "");
|
||||||
|
if (newType.getQualifier().hasLayout())
|
||||||
|
error(memberLoc, "cannot add layout to redeclared block member", member->type->getFieldName().c_str(), "");
|
||||||
|
if (newType.getQualifier().patch)
|
||||||
|
error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), "");
|
||||||
|
oldType.getQualifier().centroid = newType.getQualifier().centroid;
|
||||||
|
oldType.getQualifier().sample = newType.getQualifier().sample;
|
||||||
|
oldType.getQualifier().invariant = newType.getQualifier().invariant;
|
||||||
|
oldType.getQualifier().smooth = newType.getQualifier().smooth;
|
||||||
|
oldType.getQualifier().flat = newType.getQualifier().flat;
|
||||||
|
oldType.getQualifier().nopersp = newType.getQualifier().nopersp;
|
||||||
|
|
||||||
// TODO: SSO/4.10 semantics: block redeclaration: member type/qualifier matching
|
// go to next member
|
||||||
|
++member;
|
||||||
|
} else {
|
||||||
|
// Use EbtVoid to tag missing members of anonymous blocks that have been redeclared,
|
||||||
|
// to hide the original (shared) declaration.
|
||||||
|
// (Instance-named blocks can just have the member removed.)
|
||||||
|
if (instanceName)
|
||||||
|
member = type.getStruct()->erase(member);
|
||||||
|
else {
|
||||||
|
member->type->setElementType(EbtVoid, 1, 0, 0, 0);
|
||||||
|
++member;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numOriginalMembersFound < newTypeList.size())
|
||||||
|
error(loc, "block redeclaration has extra members", blockName.c_str(), "");
|
||||||
|
if (type.isArray() != (arraySizes != 0))
|
||||||
|
error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), "");
|
||||||
|
else if (type.isArray() && type.getArraySize() > 0 && type.getArraySize() != arraySizes->getSize())
|
||||||
|
error(loc, "cannot change array size of redeclared block", blockName.c_str(), "");
|
||||||
|
|
||||||
symbolTable.insert(*block);
|
symbolTable.insert(*block);
|
||||||
|
|
||||||
|
// Check for general layout qualifier errors
|
||||||
|
layoutTypeCheck(loc, *block);
|
||||||
|
|
||||||
// Save it in the AST for linker use.
|
// Save it in the AST for linker use.
|
||||||
intermediate.addSymbolLinkageNode(linkage, *block);
|
intermediate.addSymbolLinkageNode(linkage, *block);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TParseContext::paramCheckFix(TSourceLoc loc, const TStorageQualifier& qualifier, TType& type)
|
void TParseContext::paramCheckFix(TSourceLoc loc, const TStorageQualifier& qualifier, TType& type)
|
||||||
|
@ -2451,6 +2491,15 @@ void TParseContext::inductiveLoopCheck(TSourceLoc loc, TIntermNode* init, TInter
|
||||||
inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
|
inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do limit checks against for all built-in arrays.
|
||||||
|
void TParseContext::arrayLimitCheck(TSourceLoc loc, const TString& identifier, int size)
|
||||||
|
{
|
||||||
|
if (identifier.compare("gl_TexCoord") == 0)
|
||||||
|
limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size");
|
||||||
|
else if (identifier.compare("gl_ClipDistance") == 0)
|
||||||
|
limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size");
|
||||||
|
}
|
||||||
|
|
||||||
// See if the provide value is less than the symbol indicated by limit,
|
// See if the provide value is less than the symbol indicated by limit,
|
||||||
// which should be a constant in the symbol table.
|
// which should be a constant in the symbol table.
|
||||||
void TParseContext::limitCheck(TSourceLoc loc, int value, const char* limit, const char* feature)
|
void TParseContext::limitCheck(TSourceLoc loc, int value, const char* limit, const char* feature)
|
||||||
|
@ -3348,18 +3397,6 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
|
||||||
//
|
//
|
||||||
void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
|
void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
|
||||||
{
|
{
|
||||||
// This might be a redeclaration of a built-in block, find out, and get
|
|
||||||
// a modifiable copy if so.
|
|
||||||
if (redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Basic error checks
|
|
||||||
if (reservedErrorCheck(loc, *blockName))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (instanceName && reservedErrorCheck(loc, *instanceName))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (profile == EEsProfile && arraySizes)
|
if (profile == EEsProfile && arraySizes)
|
||||||
arraySizeRequiredCheck(loc, arraySizes->getSize());
|
arraySizeRequiredCheck(loc, arraySizes->getSize());
|
||||||
|
|
||||||
|
@ -3392,7 +3429,7 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
|
||||||
pipeInOutFix(memberLoc, memberQualifier);
|
pipeInOutFix(memberLoc, memberQualifier);
|
||||||
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
|
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage)
|
||||||
error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
|
error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||||
if ((currentBlockQualifier.storage == EvqUniform && memberQualifier.isInterpolation()) || memberQualifier.isAuxiliary())
|
if (currentBlockQualifier.storage == EvqUniform && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary()))
|
||||||
error(memberLoc, "member of uniform block cannot have an auxiliary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
|
error(memberLoc, "member of uniform block cannot have an auxiliary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
|
||||||
|
|
||||||
TBasicType basicType = typeList[member].type->getBasicType();
|
TBasicType basicType = typeList[member].type->getBasicType();
|
||||||
|
@ -3400,6 +3437,20 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
|
||||||
error(memberLoc, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), "");
|
error(memberLoc, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will
|
||||||
|
// do all the rest.
|
||||||
|
if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) {
|
||||||
|
redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a redeclaration of a built-in; check that all names are user names.
|
||||||
|
reservedErrorCheck(loc, *blockName);
|
||||||
|
if (instanceName)
|
||||||
|
reservedErrorCheck(loc, *instanceName);
|
||||||
|
for (unsigned int member = 0; member < typeList.size(); ++member)
|
||||||
|
reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName());
|
||||||
|
|
||||||
// Make default block qualification, and adjust the member qualifications
|
// Make default block qualification, and adjust the member qualifications
|
||||||
|
|
||||||
TQualifier defaultQualification;
|
TQualifier defaultQualification;
|
||||||
|
@ -3427,14 +3478,14 @@ void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TStr
|
||||||
memberQualifier = newMemberQualification;
|
memberQualifier = newMemberQualification;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Build and add the interface block as a new type named blockName
|
|
||||||
//
|
|
||||||
|
|
||||||
// reverse merge, so that currentBlockQualifier now has all layout information
|
// reverse merge, so that currentBlockQualifier now has all layout information
|
||||||
// (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers)
|
// (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers)
|
||||||
mergeObjectLayoutQualifiers(loc, currentBlockQualifier, defaultQualification);
|
mergeObjectLayoutQualifiers(loc, currentBlockQualifier, defaultQualification);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build and add the interface block as a new type named 'blockName'
|
||||||
|
//
|
||||||
|
|
||||||
TType blockType(&typeList, *blockName, currentBlockQualifier);
|
TType blockType(&typeList, *blockName, currentBlockQualifier);
|
||||||
if (arraySizes)
|
if (arraySizes)
|
||||||
blockType.setArraySizes(arraySizes);
|
blockType.setArraySizes(arraySizes);
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
const char *szExtraInfoFormat, ...);
|
const char *szExtraInfoFormat, ...);
|
||||||
void C_DECL warn(TSourceLoc, const char *szReason, const char *szToken,
|
void C_DECL warn(TSourceLoc, const char *szReason, const char *szToken,
|
||||||
const char *szExtraInfoFormat, ...);
|
const char *szExtraInfoFormat, ...);
|
||||||
bool reservedErrorCheck(TSourceLoc, const TString&);
|
void reservedErrorCheck(TSourceLoc, const TString&);
|
||||||
void reservedPpErrorCheck(TSourceLoc, const char* name, const char* op);
|
void reservedPpErrorCheck(TSourceLoc, const char* name, const char* op);
|
||||||
bool lineContinuationCheck(TSourceLoc, bool endOfComment);
|
bool lineContinuationCheck(TSourceLoc, bool endOfComment);
|
||||||
bool builtInName(const TString&);
|
bool builtInName(const TString&);
|
||||||
|
@ -125,7 +125,7 @@ public:
|
||||||
void parameterSamplerCheck(TSourceLoc, TStorageQualifier qualifier, const TType& type);
|
void parameterSamplerCheck(TSourceLoc, TStorageQualifier qualifier, const TType& type);
|
||||||
bool containsSampler(const TType& type);
|
bool containsSampler(const TType& type);
|
||||||
TSymbol* redeclareBuiltinVariable(TSourceLoc, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration);
|
TSymbol* redeclareBuiltinVariable(TSourceLoc, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration);
|
||||||
bool redeclareBuiltinBlock(TSourceLoc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
|
void redeclareBuiltinBlock(TSourceLoc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
|
||||||
void paramCheckFix(TSourceLoc, const TStorageQualifier&, TType& type);
|
void paramCheckFix(TSourceLoc, const TStorageQualifier&, TType& type);
|
||||||
void paramCheckFix(TSourceLoc, const TQualifier&, TType& type);
|
void paramCheckFix(TSourceLoc, const TQualifier&, TType& type);
|
||||||
void nestedBlockCheck(TSourceLoc);
|
void nestedBlockCheck(TSourceLoc);
|
||||||
|
@ -134,6 +134,7 @@ public:
|
||||||
void opaqueCheck(TSourceLoc, const TType&, const char* op);
|
void opaqueCheck(TSourceLoc, const TType&, const char* op);
|
||||||
void structTypeCheck(TSourceLoc, TPublicType&);
|
void structTypeCheck(TSourceLoc, TPublicType&);
|
||||||
void inductiveLoopCheck(TSourceLoc, TIntermNode* init, TIntermLoop* loop);
|
void inductiveLoopCheck(TSourceLoc, TIntermNode* init, TIntermLoop* loop);
|
||||||
|
void arrayLimitCheck(TSourceLoc, const TString&, int size);
|
||||||
void limitCheck(TSourceLoc, int value, const char* limit, const char* feature);
|
void limitCheck(TSourceLoc, int value, const char* limit, const char* feature);
|
||||||
|
|
||||||
void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
|
void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче