Block/structure fixes: Merge qualifiers with multiple declarators, handle arrays of blocks, more semantic checks for what's allowed.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21883 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-06-06 18:31:21 +00:00
parent ceb0623823
commit 0fbb0c4930
6 changed files with 81 additions and 30 deletions

38
Test/300block.frag Normal file
View File

@ -0,0 +1,38 @@
#version 300 es
struct S {
vec4 u;
uvec4 v;
isampler3D sampler;
vec3 w;
struct T1 { // ERROR
int a;
} t;
};
uniform S s;
uniform fooBlock {
uvec4 bv;
mat2 bm2;
isampler2D sampler; // ERROR
struct T2 { // ERROR
int a;
} t;
S fbs;
};
uniform barBlock {
uvec4 nbv;
int ni;
} inst;
uniform barBlockArray {
uvec4 nbv;
int ni;
} insts[4];
void main()
{
texture(s.sampler, vec3(inst.ni, bv.y, insts[2].nbv.z));
}

View File

@ -27,6 +27,7 @@ comment.frag
300layout.vert
300layout.frag
300operations.frag
300block.frag
330.frag
330comp.frag
constErrors.frag

View File

@ -392,7 +392,7 @@ typedef std::map<TTypeList*, TTypeList*>::const_iterator TStructureMapIterator;
class TType {
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
basicType(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
fieldName(0), mangled(0), typeName(0)
@ -416,7 +416,10 @@ public:
basicType(p.basicType), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
{
sampler = p.sampler;
if (basicType == EbtSampler)
sampler = p.sampler;
else
sampler.clear();
qualifier = p.qualifier;
if (p.userDef) {
structure = p.userDef->getStruct();
@ -494,6 +497,21 @@ public:
arrayInformationType = 0; // arrayInformationType should not be set for builtIn symbol table level
}
// Merge type from parent, where a parentType is at the beginning of a declaration,
// establishing some charastics for all subsequent names, while this type
// is on the individual names.
void mergeType(const TPublicType& parentType)
{
// arrayness is currently the only child aspect that has to be preserved
setElementType(parentType.basicType, parentType.vectorSize, parentType.matrixCols, parentType.matrixRows, parentType.userDef);
qualifier = parentType.qualifier;
sampler = parentType.sampler;
if (parentType.arraySizes)
setArraySizes(parentType.arraySizes);
if (parentType.userDef)
setTypeName(parentType.userDef->getTypeName());
}
TType* clone(const TStructureMap& remapper)
{
TType *newType = new TType();

View File

@ -676,7 +676,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
break;
}
// Do non in/out error checks
// Do non-in/out error checks
if (qualifier.storage != EvqUniform && samplerErrorCheck(line, publicType, "samplers and images must be uniform"))
return true;
@ -1517,7 +1517,7 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
return;
}
// check for qualifiers that don't belong within a block
// check for qualifiers and types that don't belong within a block
for (unsigned int member = 0; member < typeList.size(); ++member) {
TQualifier memberQualifier = typeList[member].type->getQualifier();
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal &&
@ -1531,6 +1531,12 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
recover();
}
}
TBasicType basicType = typeList[member].type->getBasicType();
if (basicType == EbtSampler) {
error(line, "member of block cannot be a sampler type", typeList[member].type->getFieldName().c_str(), "");
recover();
}
}
// Make default block qualification, and adjust the member qualifications
@ -1546,6 +1552,8 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
// Build and add the interface block as a new type named blockName
TType blockType(&typeList, blockName, publicType.qualifier.storage);
if (arraySizes)
blockType.setArraySizes(arraySizes);
blockType.getQualifier().layoutPacking = defaultQualification.layoutPacking;
TVariable* userTypeDef = new TVariable(&blockName, blockType, true);
if (! symbolTable.insert(*userTypeDef)) {

View File

@ -1600,11 +1600,11 @@ fully_specified_type
parseContext.recover();
$2.arraySizes = 0;
}
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))
parseContext.recover();
$$ = $2;
$$.qualifier = $1.qualifier;
if ($$.qualifier.precision == EpqNone)
$$.qualifier.precision = $2.qualifier.precision;
if (! $$.qualifier.isInterpolation() && parseContext.language == EShLangFragment)
$$.qualifier.smooth = true;
@ -2560,6 +2560,10 @@ precision_qualifier
struct_specifier
: STRUCT IDENTIFIER LEFT_BRACE struct_declaration_list RIGHT_BRACE {
// TODO: semantics: check for qualifiers that don't belong in a struct
// TODO: semantics: check that this is not nested inside a block or structure
// parseContext.error($1.line, "cannot nest a block or structure definitions", $1.userDef->getTypeName().c_str(), "");
TType* structure = new TType($4, *$2.string);
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
if (! parseContext.symbolTable.insert(*userTypeDef)) {
@ -2608,17 +2612,8 @@ struct_declaration
if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
parseContext.recover();
}
for (unsigned int i = 0; i < $$->size(); ++i) {
//
// Careful not to replace already know aspects of type, like array-ness
//
(*$$)[i].type->setElementType($1.basicType, $1.vectorSize, $1.matrixCols, $1.matrixRows, $1.userDef);
if ($1.arraySizes)
(*$$)[i].type->setArraySizes($1.arraySizes);
if ($1.userDef)
(*$$)[i].type->setTypeName($1.userDef->getTypeName());
}
for (unsigned int i = 0; i < $$->size(); ++i)
(*$$)[i].type->mergeType($1);
}
| type_qualifier type_specifier struct_declarator_list SEMICOLON {
if ($2.arraySizes) {
@ -2632,17 +2627,8 @@ struct_declaration
parseContext.recover();
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))
parseContext.recover();
for (unsigned int i = 0; i < $$->size(); ++i) {
//
// Careful not to replace already know aspects of type, like array-ness
//
(*$$)[i].type->setElementType($2.basicType, $2.vectorSize, $2.matrixCols, $2.matrixRows, $2.userDef);
(*$$)[i].type->getQualifier() = $2.qualifier;
if ($2.arraySizes)
(*$$)[i].type->setArraySizes($2.arraySizes);
if ($2.userDef)
(*$$)[i].type->setTypeName($2.userDef->getTypeName());
}
for (unsigned int i = 0; i < $$->size(); ++i)
(*$$)[i].type->mergeType($2);
}
;

View File

@ -982,7 +982,7 @@ static int macro_scan(InputSrc *inInput, yystypepp * yylvalpp)
// return a zero, for scanning a macro that was never defined
static int zero_scan(InputSrc *inInput, yystypepp * yylvalpp)
{
MacroInputSrc* in = (MacroInputSrc*)inInput; //?? need to free this?
MacroInputSrc* in = (MacroInputSrc*)inInput;
strcpy(yylvalpp->symbol_name, "0");
yylvalpp->sc_int = 0;