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:
John Kessenich 2013-12-09 00:37:46 +00:00
Родитель e1b2e39a56
Коммит c719481d43
16 изменённых файлов: 229 добавлений и 127 удалений

Просмотреть файл

@ -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&);