Semantic checks for .length(), switch/case/default, and multidimensional arrays.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@22175 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-06-26 05:54:40 +00:00
parent ef84d10e4c
commit e369bfccfe
9 changed files with 144 additions and 71 deletions

View file

@ -461,10 +461,10 @@ bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* nod
// Both test, and if necessary spit out an error, to see if the node is really
// a constant.
//
void TParseContext::constCheck(TIntermTyped* node)
void TParseContext::constCheck(TIntermTyped* node, const char* token)
{
if (node->getQualifier().storage != EvqConst)
error(node->getLine(), "constant expression required", "", "");
error(node->getLine(), "constant expression required", token, "");
}
//
@ -996,6 +996,28 @@ void TParseContext::arraySizeRequiredCheck(int line, int& size)
}
}
void TParseContext::arrayDimError(int line)
{
requireProfile(line, (EProfileMask)(ECoreProfileMask | ECompatibilityProfileMask), "arrays of arrays");
profileRequires(line, ECoreProfile, 430, 0, "arrays of arrays");
profileRequires(line, ECompatibilityProfile, 430, 0, "arrays of arrays");
}
void TParseContext::arrayDimCheck(int line, TArraySizes sizes1, TArraySizes sizes2)
{
if (sizes1 && sizes2 ||
sizes1 && sizes1->size() > 1 ||
sizes2 && sizes2->size() > 1)
arrayDimError(line);
}
void TParseContext::arrayDimCheck(int line, const TType* type, TArraySizes sizes2)
{
if (type && type->isArray() && sizes2 ||
sizes2 && sizes2->size() > 1)
arrayDimError(line);
}
//
// Do all the semantic checking for declaring an array, with and
// without a size, and make the right changes to the symbol table.
@ -1582,6 +1604,8 @@ void TParseContext::addBlock(int line, TTypeList& typeList, const TString* insta
return;
}
arrayDimCheck(line, arraySizes, 0);
// 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();
@ -1774,10 +1798,26 @@ void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TInter
statements->setOperator(EOpSequence);
switchSequence->push_back(statements);
}
if (branchNode)
if (branchNode) {
// check all previous cases for the same label (or both are 'default')
for (unsigned int s = 0; s < switchSequence->size(); ++s) {
TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode();
if (prevBranch) {
TIntermTyped* prevExpression = prevBranch->getExpression();
TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression();
if (prevExpression == 0 && newExpression == 0)
error(branchNode->getLine(), "duplicate label", "default", "");
else if (prevExpression != 0 &&
newExpression != 0 &&
prevExpression->getAsConstantUnion() &&
newExpression->getAsConstantUnion() &&
prevExpression->getAsConstantUnion()->getUnionArrayPointer()->getIConst() ==
newExpression->getAsConstantUnion()->getUnionArrayPointer()->getIConst())
error(branchNode->getLine(), "duplicated value", "case", "");
}
}
switchSequence->push_back(branchNode);
// TODO: semantics: verify no duplicated case values
}
}
//