Commit fd8e1010 by John Kessenich

Simply compile-time error handling: mostly removed the need to test an error…

Simply compile-time error handling: mostly removed the need to test an error occurred and the need to call recover(). git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21959 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent fbe01520
......@@ -43,7 +43,7 @@
TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, int v, EProfile p, EShLanguage L, TInfoSink& is,
bool fc, EShMessages m) :
intermediate(interm), symbolTable(symt), infoSink(is), language(L), treeRoot(0),
recoveredFromError(false), numErrors(0), lexAfterType(false), loopNestingLevel(0),
numErrors(0), lexAfterType(false), loopNestingLevel(0),
inTypeParen(false),
version(v), profile(p), forwardCompatible(fc), messages(m),
contextPragma(true, false)
......@@ -97,6 +97,8 @@ const char* TParseContext::getPreamble()
// Look at a '.' field selector string and change it into offsets
// for a vector.
//
// Returns true if there is no error.
//
bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
{
fields.num = (int) compString.size();
......@@ -192,15 +194,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV
////////////////////////////////////////////////////////////////////////
//
// Track whether errors have occurred.
//
void TParseContext::recover()
{
recoveredFromError = true;
}
//
// Used by flex/bison to output all syntax and parsing errors.
// Used to output syntax, parsing, and semantic errors.
//
void C_DECL TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...)
......@@ -242,10 +236,8 @@ TIntermTyped* TParseContext::handleVariable(int line, TSymbol* symbol, TString*
// The symbol table search was done in the lexical phase, but
// if this is a new symbol, it wouldn't have found it.
const TVariable* variable = symbol ? symbol->getAsVariable() : 0;
if (symbol && ! variable) {
if (symbol && ! variable)
error(line, "variable name expected", string->c_str(), "");
recover();
}
if (! variable)
variable = new TVariable(string, TType(EbtVoid));
......@@ -299,7 +291,7 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
// it was not found as a variable in the symbol table. If so, give the error
// message and insert a dummy variable in the symbol table to prevent future errors.
//
void TParseContext::variableErrorCheck(TIntermTyped*& nodePtr)
void TParseContext::variableCheck(TIntermTyped*& nodePtr)
{
TIntermSymbol* symbol = nodePtr->getAsSymbolNode();
if (! symbol)
......@@ -307,7 +299,6 @@ void TParseContext::variableErrorCheck(TIntermTyped*& nodePtr)
if (symbol->getType().getBasicType() == EbtVoid) {
error(symbol->getLine(), "undeclared identifier", symbol->getSymbol().c_str(), "");
recover();
// Add to symbol table to prevent future error messages on the same name
......@@ -437,48 +428,32 @@ 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.
//
// Returns true if the was an error.
//
bool TParseContext::constErrorCheck(TIntermTyped* node)
void TParseContext::constCheck(TIntermTyped* node)
{
if (node->getQualifier().storage == EvqConst)
return false;
error(node->getLine(), "constant expression required", "", "");
return true;
if (node->getQualifier().storage != EvqConst)
error(node->getLine(), "constant expression required", "", "");
}
//
// Both test, and if necessary spit out an error, to see if the node is really
// an integer.
//
// Returns true if the was an error.
//
bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
void TParseContext::integerCheck(TIntermTyped* node, const char* token)
{
if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar() && ! node->isArray())
return false;
return;
error(node->getLine(), "scalar integer expression required", token, "");
return true;
}
//
// Both test, and if necessary spit out an error, to see if we are currently
// globally scoped.
//
// Returns true if the was an error.
//
bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
void TParseContext::globalCheck(int line, bool global, const char* token)
{
if (global)
return false;
error(line, "only allowed at global scope", token, "");
return true;
if (! global)
error(line, "only allowed at global scope", token, "");
}
//
......@@ -486,8 +461,6 @@ bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
// of scope. Except, if the symbol table is at the built-in push-level,
// which is when we are parsing built-ins.
//
// Returns true if there was an error.
//
bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
{
if (!symbolTable.atBuiltInLevel()) {
......@@ -513,7 +486,7 @@ bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
//
// Returns true if there was an error in construction.
//
bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
bool TParseContext::constructorError(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
{
*type = function.getReturnType();
......@@ -640,32 +613,18 @@ bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TP
return false;
}
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
//
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
// Checks to see if the node (for the expression) contains a scalar boolean expression or not
void TParseContext::boolCheck(int line, const TIntermTyped* type)
{
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
error(line, "boolean expression expected", "", "");
return true;
}
return false;
}
// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
//
// returns true in case of an error
//
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
void TParseContext::boolCheck(int line, const TPublicType& pType)
{
if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) {
if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1))
error(line, "boolean expression expected", "", "");
return true;
}
return false;
}
bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
......@@ -687,10 +646,10 @@ bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const
return false;
}
bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualifier, const TPublicType& publicType)
void TParseContext::globalQualifierFix(int line, TQualifier& qualifier, const TPublicType& publicType)
{
if (! symbolTable.atGlobalLevel())
return false;
return;
// First, move from parameter qualifiers to shader in/out qualifiers
......@@ -712,7 +671,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
qualifier.storage = EvqVaryingIn;
error(line, "cannot use 'inout' at global scope", "", "");
return true;
return;
default:
break;
}
......@@ -720,22 +679,24 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
// Do non-in/out error checks
if (qualifier.storage != EvqUniform && samplerErrorCheck(line, publicType, "samplers and images must be uniform"))
return true;
return;
if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
return false;
return;
// now, knowing it is a shader in/out, do all the in/out semantic checks
if (publicType.basicType == EbtBool) {
error(line, "cannot be bool", getStorageQualifierString(qualifier.storage), "");
return true;
return;
}
if (language == EShLangVertex && qualifier.storage == EvqVaryingIn) {
if (publicType.basicType == EbtStruct) {
error(line, "cannot be a structure or array", getStorageQualifierString(qualifier.storage), "");
return true;
return;
}
if (publicType.arraySizes) {
requireProfile(line, (EProfileMask)~EEsProfileMask, "vertex input arrays");
......@@ -747,7 +708,8 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
profileRequires(line, EEsProfile, 300, 0, "fragment shader output");
if (publicType.basicType == EbtStruct) {
error(line, "cannot be a structure", getStorageQualifierString(qualifier.storage), "");
return true;
return;
}
}
......@@ -757,7 +719,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
language != EShLangFragment && qualifier.storage == EvqVaryingOut && ! qualifier.flat) {
error(line, "must be qualified as 'flat'", getStorageQualifierString(qualifier.storage), TType::getBasicString(publicType.basicType));
return true;
return;
}
}
......@@ -765,10 +727,8 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
(qualifier.isAuxillary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant)) {
error(line, "vertex input cannot be further qualified", "", "");
return true;
return;
}
return false;
}
//
......@@ -776,9 +736,7 @@ bool TParseContext::globalQualifierFixAndErrorCheck(int line, TQualifier& qualif
// If there is duplication, issue error messages, unless 'force'
// is specified, which means to just override default settings.
//
// Return true if there was an error.
//
bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force)
void TParseContext::mergeQualifiers(int line, TPublicType& dst, const TPublicType& src, bool force)
{
bool bad = false;
......@@ -825,8 +783,6 @@ bool TParseContext::mergeQualifiersErrorCheck(int line, TPublicType& dst, const
if (bad)
error(line, "replicated qualifiers", "", "");
return bad;
}
void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrecisionQualifier qualifier)
......@@ -844,18 +800,12 @@ void TParseContext::setDefaultPrecision(int line, TPublicType& publicType, TPrec
}
error(line, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), "");
recover();
}
bool TParseContext::parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type)
void TParseContext::parameterSamplerCheck(int line, TStorageQualifier qualifier, const TType& type)
{
if ((qualifier == EvqOut || qualifier == EvqInOut) &&
type.getBasicType() != EbtStruct && type.getBasicType() == EbtSampler) {
if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && type.getBasicType() == EbtSampler)
error(line, "samplers cannot be output parameters", type.getCompleteTypeString().c_str(), "");
return true;
}
return false;
}
bool TParseContext::containsSampler(const TType& type)
......@@ -904,15 +854,14 @@ bool TParseContext::insertBuiltInArrayAtGlobalLevel()
//
// Do size checking for an array type's size.
//
// Returns true if there was an error.
//
bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
void TParseContext::arraySizeCheck(int line, TIntermTyped* expr, int& size)
{
TIntermConstantUnion* constant = expr->getAsConstantUnion();
if (constant == 0 || (constant->getBasicType() != EbtInt && constant->getBasicType() != EbtUint)) {
error(line, "array size must be a constant integer expression", "", "");
size = 1;
return true;
return;
}
size = constant->getUnionArrayPointer()->getIConst();
......@@ -920,10 +869,9 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
if (size <= 0) {
error(line, "array size must be a positive integer", "", "");
size = 1;
return true;
}
return false;
return;
}
}
//
......@@ -931,7 +879,7 @@ bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
//
// Returns true if there is an error.
//
bool TParseContext::arrayQualifierErrorCheck(int line, const TPublicType& type)
bool TParseContext::arrayQualifierError(int line, const TPublicType& type)
{
if (type.qualifier.storage == EvqConst)
profileRequires(line, ENoProfile, 120, "GL_3DL_array_objects", "const array");
......@@ -947,18 +895,12 @@ bool TParseContext::arrayQualifierErrorCheck(int line, const TPublicType& type)
//
// Require array to have size
//
// Returns true if there is an error.
//
bool TParseContext::arraySizeRequiredErrorCheck(int line, int& size)
void TParseContext::arraySizeRequiredCheck(int line, int& size)
{
if (size == 0) {
error(line, "array size required", "", "");
size = 1;
return true;
}
return false;
}
//
......@@ -967,9 +909,7 @@ bool TParseContext::arraySizeRequiredErrorCheck(int line, int& size)
//
// size == 0 means no specified size.
//
// Returns true if there was an error.
//
bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublicType& type, TVariable*& variable)
void TParseContext::arrayCheck(int line, TString& identifier, const TPublicType& type, TVariable*& variable)
{
//
// Don't check for reserved word use until after we know it's not in the symbol table,
......@@ -980,42 +920,43 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublic
TSymbol* symbol = symbolTable.find(identifier, 0, &sameScope);
if (symbol == 0 || !sameScope) {
if (reservedErrorCheck(line, identifier))
return true;
return;
variable = new TVariable(&identifier, TType(type));
if (! symbolTable.insert(*variable)) {
delete variable;
error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
return true;
return;
}
} else {
variable = symbol->getAsVariable();
if (! variable) {
error(line, "array variable name expected", identifier.c_str(), "");
return true;
return;
}
if (! variable->getType().isArray()) {
error(line, "redeclaring non-array as array", identifier.c_str(), "");
return true;
return;
}
if (variable->getType().getArraySize() > 0) {
error(line, "redeclaration of array with size", identifier.c_str(), "");
return true;
return;
}
if (! variable->getType().sameElementType(TType(type))) {
error(line, "redeclaration of array with a different type", identifier.c_str(), "");
return true;
return;
}
TType* t = variable->getArrayInformationType();
while (t != 0) {
if (t->getMaxArraySize() > type.arraySizes->front()) {
error(line, "higher index value already used for the array", identifier.c_str(), "");
return true;
return;
}
t->setArraySizes(type.arraySizes);
t = t->getArrayInformationType();
......@@ -1024,10 +965,7 @@ bool TParseContext::arrayErrorCheck(int line, TString& identifier, const TPublic
variable->getType().setArraySizes(type.arraySizes);
}
if (voidErrorCheck(line, identifier, type))
return true;
return false;
voidErrorCheck(line, identifier, type);
}
bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
......@@ -1084,9 +1022,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
//
// Enforce non-initializer type/qualifier rules.
//
// Returns true if there was an error.
//
bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type)
void TParseContext::nonInitConstCheck(int line, TString& identifier, TPublicType& type)
{
//
// Make the qualifier make sense.
......@@ -1094,56 +1030,45 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
if (type.qualifier.storage == EvqConst) {
type.qualifier.storage = EvqTemporary;
error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
return true;
}
return false;
}
//
// Do semantic checking for a variable declaration that has no initializer,
// and update the symbol table.
//
// Returns true if there was an error.
//
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
void TParseContext::nonInitCheck(int line, TString& identifier, TPublicType& type)
{
if (reservedErrorCheck(line, identifier))
recover();
reservedErrorCheck(line, identifier);
TVariable* variable = new TVariable(&identifier, TType(type));
if (! symbolTable.insert(*variable)) {
error(line, "redefinition", variable->getName().c_str(), "");
delete variable;
return true;
}
if (voidErrorCheck(line, identifier, type))
return true;
return false;
} else
voidErrorCheck(line, identifier, type);
}
bool TParseContext::paramErrorCheck(int line, TStorageQualifier qualifier, TType* type)
void TParseContext::paramCheck(int line, TStorageQualifier qualifier, TType* type)
{
switch (qualifier) {
case EvqConst:
case EvqConstReadOnly:
type->getQualifier().storage = EvqConstReadOnly;
return false;
break;
case EvqIn:
case EvqOut:
case EvqInOut:
type->getQualifier().storage = qualifier;
return false;
break;
case EvqTemporary:
type->getQualifier().storage = EvqIn;
return false;
break;
default:
type->getQualifier().storage = EvqIn;
error(line, "qualifier not allowed on function parameter", getStorageQualifierString(qualifier), "");
return true;
break;
}
}
......@@ -1242,8 +1167,8 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *bu
// Initializers show up in several places in the grammar. Have one set of
// code to handle them here.
//
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
bool TParseContext::executeInitializerError(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{
TType type(pType);
......@@ -1482,7 +1407,6 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
default:
error(line, "unsupported construction", "", "");
recover();
return 0;
}
......@@ -1515,8 +1439,7 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
if (! converted || converted->getType() != type) {
error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
node->getAsTyped()->getType().getCompleteTypeString().c_str(), type.getCompleteTypeString().c_str());
recover();
return 0;
}
......@@ -1530,19 +1453,14 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
{
// First, error checks
if (reservedErrorCheck(line, blockName)) {
recover();
if (reservedErrorCheck(line, blockName))
return;
}
if (instanceName && reservedErrorCheck(line, *instanceName)) {
recover();
if (instanceName && reservedErrorCheck(line, *instanceName))
return;
}
if (publicType.basicType != EbtVoid) {
error(line, "interface blocks cannot be declared with a type", blockName.c_str(), "");
recover();
return;
}
......@@ -1551,7 +1469,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
profileRequires(line, EEsProfile, 300, 0, "uniform block");
} else {
error(line, "only uniform interface blocks are supported", blockName.c_str(), "");
recover();
return;
}
......@@ -1559,23 +1476,14 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
// 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 &&
memberQualifier.storage != publicType.qualifier.storage) {
if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != publicType.qualifier.storage)
error(line, "member storage qualifier cannot contradict block storage qualifier", typeList[member].type->getFieldName().c_str(), "");
recover();
}
if (publicType.qualifier.storage == EvqUniform) {
if (memberQualifier.isInterpolation() || memberQualifier.isAuxillary()) {
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
recover();
}
}
if (publicType.qualifier.storage == EvqUniform && memberQualifier.isInterpolation() || memberQualifier.isAuxillary())
error(line, "member of uniform block cannot have an auxillary or interpolation qualifier", typeList[member].type->getFieldName().c_str(), "");
TBasicType basicType = typeList[member].type->getBasicType();
if (basicType == EbtSampler) {
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
......@@ -1597,7 +1505,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
TVariable* userTypeDef = new TVariable(&blockName, blockType, true);
if (! symbolTable.insert(*userTypeDef)) {
error(line, "redefinition", blockName.c_str(), "block name");
recover();
return;
}
......@@ -1614,7 +1521,6 @@ void TParseContext::addBlock(int line, TPublicType& publicType, const TString& b
error(line, "nameless block contains a member that already has a name at global scope", blockName.c_str(), "");
else
error(line, "block instance name redefinition", variable->getName().c_str(), "");
recover();
return;
}
......@@ -1631,10 +1537,8 @@ void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TInter
TIntermSequence* switchSequence = switchSequenceStack.back();
if (statements) {
if (switchSequence->size() == 0) {
if (switchSequence->size() == 0)
error(statements->getLine(), "cannot have statements before first case/default label", "switch", "");
recover();
}
statements->setOperator(EOpSequence);
switchSequence->push_back(statements);
}
......@@ -1657,10 +1561,8 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter
if (expression == 0 ||
expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint ||
expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) {
expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector())
error(line, "condition must be a scalar integer expression", "switch", "");
recover();
}
// If there is nothing to do, drop the switch but still execute the expression
TIntermSequence* switchSequence = switchSequenceStack.back();
......@@ -1669,7 +1571,6 @@ TIntermNode* TParseContext::addSwitch(int line, TIntermTyped* expression, TInter
if (lastStatements == 0) {
error(line, "last case/default label must be followed by statements", "switch", "");
recover();
return expression;
}
......@@ -1708,10 +1609,8 @@ void TParseContext::updateDefaults(int line, const TPublicType& publicType, cons
}
}
if (cantHaveId && id) {
if (cantHaveId && id)
error(line, "cannot set global layout qualifiers on uniform variable, use just 'uniform' or a block", id->c_str(), "");
recover();
}
}
//
......@@ -1732,13 +1631,11 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
if (!unionArray) { // this error message should never be raised
infoSink.info.message(EPrefixInternalError, "constUnion not initialized in addConstVectorNode function", line);
recover();
return node;
}
} else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
error(line, "Cannot offset into the vector", "Error", "");
recover();
return 0;
}
......@@ -1748,14 +1645,13 @@ TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTy
for (int i = 0; i < fields.num; i++) {
if (fields.offsets[i] >= node->getType().getObjectSize()) {
error(line, "", "[", "vector index out of range '%d'", fields.offsets[i]);
recover();
fields.offsets[i] = 0;
}
constArray[i] = unionArray[fields.offsets[i]];
}
typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
return typedNode;
}
......@@ -1772,7 +1668,6 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
if (index >= node->getType().getMatrixCols()) {
error(line, "", "[", "matrix field selection out of range '%d'", index);
recover();
index = 0;
}
......@@ -1783,7 +1678,6 @@ TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, T
typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
} else {
error(line, "Cannot offset into the matrix", "Error", "");
recover();
return 0;
}
......@@ -1808,7 +1702,6 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
if (index >= node->getType().getArraySize() || index < 0) {
error(line, "", "[", "array index '%d' out of range", index);
recover();
index = 0;
}
......@@ -1819,7 +1712,6 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TS
typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
} else {
error(line, "Cannot offset into the array", "Error", "");
recover();
return 0;
}
......@@ -1855,7 +1747,6 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n
typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
} else {
error(line, "Cannot offset into the structure", "Error", "");
recover();
return 0;
}
......
......@@ -74,8 +74,7 @@ struct TParseContext {
TInfoSink& infoSink;
EShLanguage language; // vertex or fragment language
TIntermNode* treeRoot; // root of parse tree being created
bool recoveredFromError; // true if a parse error has occurred, but we continue to parse
int numErrors;
int numErrors; // number of compile-time errors encountered
bool lexAfterType; // true if we've recognized a type, so can only be looking for an identifier
int loopNestingLevel; // 0 if outside all loops
TList<TIntermSequence*> switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
......@@ -101,45 +100,44 @@ struct TParseContext {
void C_DECL error(TSourceLoc, const char *szReason, const char *szToken,
const char *szExtraInfoFormat, ...);
bool reservedErrorCheck(int line, const TString& identifier);
void recover();
TIntermTyped* handleVariable(int line, TSymbol* symbol, TString* string);
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, int line);
void assignError(int line, const char* op, TString left, TString right);
void unaryOpError(int line, const char* op, TString operand);
void binaryOpError(int line, const char* op, TString left, TString right);
void variableErrorCheck(TIntermTyped*& nodePtr);
void variableCheck(TIntermTyped*& nodePtr);
bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
bool constErrorCheck(TIntermTyped* node);
bool integerErrorCheck(TIntermTyped* node, const char* token);
bool globalErrorCheck(int line, bool global, const char* token);
bool constructorErrorCheck(int line, TIntermNode*, TFunction&, TOperator, TType*);
bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
bool arrayQualifierErrorCheck(int line, const TPublicType&);
bool arraySizeRequiredErrorCheck(int line, int& size);
bool arrayErrorCheck(int line, TString& identifier, const TPublicType&, TVariable*& variable);
void constCheck(TIntermTyped* node);
void integerCheck(TIntermTyped* node, const char* token);
void globalCheck(int line, bool global, const char* token);
bool constructorError(int line, TIntermNode*, TFunction&, TOperator, TType*);
void arraySizeCheck(int line, TIntermTyped* expr, int& size);
bool arrayQualifierError(int line, const TPublicType&);
void arraySizeRequiredCheck(int line, int& size);
void arrayCheck(int line, TString& identifier, const TPublicType&, TVariable*& variable);
bool insertBuiltInArrayAtGlobalLevel();
bool voidErrorCheck(int, const TString&, const TPublicType&);
bool boolErrorCheck(int, const TIntermTyped*);
bool boolErrorCheck(int, const TPublicType&);
void boolCheck(int, const TIntermTyped*);
void boolCheck(int, const TPublicType&);
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool globalQualifierFixAndErrorCheck(int line, TQualifier&, const TPublicType&);
void globalQualifierFix(int line, TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(int line, const TPublicType& pType);
bool mergeQualifiersErrorCheck(int line, TPublicType& dst, const TPublicType& src, bool force);
void mergeQualifiers(int line, TPublicType& dst, const TPublicType& src, bool force);
void setDefaultPrecision(int line, TPublicType&, TPrecisionQualifier);
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
void parameterSamplerCheck(int line, TStorageQualifier qualifier, const TType& type);
bool containsSampler(const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
bool paramErrorCheck(int line, TStorageQualifier qualifier, TType* type);
void nonInitConstCheck(int line, TString& identifier, TPublicType& type);
void nonInitCheck(int line, TString& identifier, TPublicType& type);
void paramCheck(int line, TStorageQualifier qualifier, TType* type);
void setLayoutQualifier(int line, TPublicType&, TString&);
void setLayoutQualifier(int line, TPublicType&, TString&, int);
void mergeLayoutQualifiers(int line, TQualifier& dest, const TQualifier& src);
const TFunction* findFunction(int line, TFunction* pfnCall, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
bool executeInitializerError(TSourceLoc line, TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
TIntermTyped* addConstructor(TIntermNode*, const TType&, TOperator, TFunction*, TSourceLoc);
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
......@@ -153,6 +151,7 @@ struct TParseContext {
TIntermTyped* addConstStruct(TString& , TIntermTyped*, TSourceLoc);
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
void requireProfile(int line, EProfileMask profileMask, const char *featureDesc);
void requireStage(int line, EShLanguageMask languageMask, const char *featureDesc);
void profileRequires(int line, EProfile callingProfile, int minVersion, int numExtensions, const char* extensions[], const char *featureDesc);
......
......@@ -66,10 +66,8 @@ const char* ProfileName[EProfileCount] = {
//
void TParseContext::requireProfile(int line, EProfileMask profileMask, const char *featureDesc)
{
if (((1 << profile) & profileMask) == 0) {
if (((1 << profile) & profileMask) == 0)
error(line, "not supported with this profile:", featureDesc, ProfileName[profile]);
recover();
}
}
//
......@@ -79,10 +77,8 @@ void TParseContext::requireProfile(int line, EProfileMask profileMask, const cha
//
void TParseContext::requireStage(int line, EShLanguageMask languageMask, const char *featureDesc)
{
if (((1 << language) & languageMask) == 0) {
if (((1 << language) & languageMask) == 0)
error(line, "not supported in this stage:", featureDesc, StageName[language]);
recover();
}
}
//
......@@ -112,10 +108,8 @@ void TParseContext::profileRequires(int line, EProfile callingProfile, int minVe
}
}
if (! okay) {
if (! okay)
error(line, "not supported for this version or the enabled extensions", featureDesc, "");
recover();
}
}
}
......@@ -133,13 +127,11 @@ void TParseContext::checkDeprecated(int line, EProfile callingProfile, int depVe
{
if (profile == callingProfile) {
if (version >= depVersion) {
if (forwardCompatible) {
if (forwardCompatible)
error(line, "deprecated, may be removed in future release", featureDesc, "");
recover();
} else if (! (messages & EShMsgSuppressWarnings)) {
else if (! (messages & EShMsgSuppressWarnings))
infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " +
String(depVersion) + "; may be removed in future release").c_str(), line);
}
}
}
}
......@@ -156,7 +148,6 @@ void TParseContext::requireNotRemoved(int line, EProfile callingProfile, int rem
char buf[maxSize];
snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName[profile], removedVersion);
error(line, "no longer supported in", featureDesc, buf);
recover();
}
}
}
......
......@@ -536,12 +536,12 @@ int yy_input(char* buf, int max_size);
0[xX]{H}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; }
0{O}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; }
0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
0{D}+ { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); return 0;}
{D}+ { pyylval->lex.line = yylineno; pyylval->lex.i = strtoul(yytext, 0, 0); return INTCONSTANT; }
0[xX]{H}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; }
0{O}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; }
0{D}+{U} { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); parseContext.recover(); return 0;}
0{D}+{U} { pyylval->lex.line = yylineno; parseContext.error(yylineno, "Invalid Octal number.", yytext, "", ""); return 0;}
{D}+{U} { pyylval->lex.line = yylineno; pyylval->lex.u = strtoul(yytext, 0, 0); return UINTCONSTANT; }
{D}+{F} { pyylval->lex.line = yylineno; pyylval->lex.d = atof(yytext); return FLOATCONSTANT; }
......@@ -657,7 +657,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
for (int i = 0; i < argc; ++i) {
if (! argv[i]) {
parseContextLocal.error(0, "Null shader source string", "", "");
parseContextLocal.recover();
return 1;
}
}
......@@ -709,7 +709,7 @@ int PaParseStrings(char* argv[], int strLen[], int argc, TParseContext& parseCon
ret = yyparse((void*)(&parseContextLocal));
#endif
delete writeablePreamble;
if (cpp->CompileError == 1 || parseContextLocal.recoveredFromError || parseContextLocal.numErrors > 0)
if (cpp->CompileError == 1 || parseContextLocal.numErrors > 0)
return 1;
else
return 0;
......@@ -725,20 +725,15 @@ void yyerror(const char *s)
TParseContext& pc = *((TParseContext *)cpp->pC);
if (pc.AfterEOF) {
if (cpp->tokensBeforeEOF == 1) {
if (cpp->tokensBeforeEOF == 1)
GlobalParseContext->error(yylineno, "", "pre-mature EOF", s, "");
GlobalParseContext->recover();
}
} else {
} else
GlobalParseContext->error(yylineno, "", yytext, s, "");
GlobalParseContext->recover();
}
}
void PaReservedWord()
{
GlobalParseContext->error(yylineno, "Reserved word.", yytext, "", "");
GlobalParseContext->recover();
}
int PaIdentOrType(const char* yytext, TParseContext& parseContextLocal, YYSTYPE* pyylval)
......@@ -907,6 +902,7 @@ int Pa2ndGenerationImage(TParseContext& pc, int line, const char* text, YYSTYPE*
return PaIdentOrType(text, pc, pyylval);
}
// TODO: CPP: is this dead code? Combine with other comment parsers.
int PaParseComment(int& lineno, TParseContext& parseContextLocal)
{
int transitionFlag = 0;
......@@ -926,14 +922,14 @@ int PaParseComment(int& lineno, TParseContext& parseContextLocal)
}
break;
case EOF :
/* Raise error message here */
parseContextLocal.error(yylineno, "End of shader found before end of comment.", "", "", "");
GlobalParseContext->recover();
return YY_NULL;
default : /* Any other character will be a part of the comment */
transitionFlag = 0;
}
}
return 1;
}
......@@ -959,7 +955,6 @@ void ShPpErrorToInfoLog(const char *msg)
TParseContext& pc = *((TParseContext *)cpp->pC);
pc.error(yylineno, "", "Preprocessor", msg, "");
GlobalParseContext->recover();
}
// return 1 if error
......
......@@ -263,13 +263,12 @@ postfix_expression
$$ = $1;
}
| postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET {
parseContext.variableErrorCheck($1);
parseContext.variableCheck($1);
if (!$1->isArray() && !$1->isMatrix() && !$1->isVector()) {
if ($1->getAsSymbolNode())
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", $1->getAsSymbolNode()->getSymbol().c_str(), "");
else
parseContext.error($2.line, " left of '[' is not of type array, matrix, or vector ", "expression", "");
parseContext.recover();
}
if ($1->getType().getQualifier().storage == EvqConst && $3->getQualifier().storage == EvqConst) {
if ($1->isArray()) { // constant folding for arrays
......@@ -286,32 +285,24 @@ postfix_expression
if ($3->getQualifier().storage == EvqConst) {
int index = $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
if (! $1->isArray() && ($1->isVector() && $1->getType().getVectorSize() <= index ||
$1->isMatrix() && $1->getType().getMatrixCols() <= index)) {
$1->isMatrix() && $1->getType().getMatrixCols() <= index))
parseContext.error($2.line, "", "[", "index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
parseContext.recover();
} else {
else {
if ($1->isArray()) {
if ($1->getType().getArraySize() == 0) {
if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst()) {
if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line))
parseContext.recover();
} else {
if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))
parseContext.recover();
}
if ($1->getType().getMaxArraySize() <= $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst())
parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst(), true, $2.line);
else
parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line);
} else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize() ||
$3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() < 0) {
$3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() < 0)
parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());
parseContext.recover();
}
}
$$ = parseContext.intermediate.addIndex(EOpIndexDirect, $1, $3, $2.line);
}
} else {
if ($1->isArray() && $1->getType().getArraySize() == 0) {
if ($1->isArray() && $1->getType().getArraySize() == 0)
parseContext.error($2.line, "", "[", "array must be redeclared with a size before being indexed with a variable");
parseContext.recover();
}
if ($1->getBasicType() == EbtBlock)
parseContext.requireProfile($1->getLine(), static_cast<EProfileMask>(~EEsProfileMask), "variable indexing block array");
......@@ -334,7 +325,7 @@ postfix_expression
$$ = $1;
}
| postfix_expression DOT FIELD_SELECTION {
parseContext.variableErrorCheck($1);
parseContext.variableCheck($1);
if ($1->isArray()) {
//
// It can only be a method (e.g., length), which can't be resolved until
......@@ -348,7 +339,6 @@ postfix_expression
$$ = parseContext.intermediate.addMethod($1, TType(EbtInt), $3.string, $2.line);
} else {
parseContext.error($3.line, "only the length method is supported for array", $3.string->c_str(), "");
parseContext.recover();
$$ = $1;
}
} else if ($1->isVector()) {
......@@ -356,15 +346,12 @@ postfix_expression
if (! parseContext.parseVectorFields(*$3.string, $1->getVectorSize(), fields, $3.line)) {
fields.num = 1;
fields.offsets[0] = 0;
parseContext.recover();
}
if ($1->getType().getQualifier().storage == EvqConst) { // constant folding for vector fields
$$ = parseContext.addConstVectorNode(fields, $1, $3.line);
if ($$ == 0) {
parseContext.recover();
if ($$ == 0)
$$ = $1;
}
else
$$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size()));
} else {
......@@ -381,15 +368,13 @@ postfix_expression
$$->setType(TType($1->getBasicType(), EvqTemporary, $1->getType().getQualifier().precision, (int) vectorString.size()));
}
}
} else if ($1->isMatrix()) {
} else if ($1->isMatrix())
parseContext.error($2.line, "field selection not allowed on matrix", ".", "");
parseContext.recover();
} else if ($1->getBasicType() == EbtStruct || $1->getBasicType() == EbtBlock) {
else if ($1->getBasicType() == EbtStruct || $1->getBasicType() == EbtBlock) {
bool fieldFound = false;
TTypeList* fields = $1->getType().getStruct();
if (fields == 0) {
parseContext.error($2.line, "structure has no fields", "Internal Error", "");
parseContext.recover();
$$ = $1;
} else {
unsigned int i;
......@@ -402,10 +387,9 @@ postfix_expression
if (fieldFound) {
if ($1->getType().getQualifier().storage == EvqConst) {
$$ = parseContext.addConstStruct(*$3.string, $1, $2.line);
if ($$ == 0) {
parseContext.recover();
if ($$ == 0)
$$ = $1;
} else {
else {
$$->setType(*(*fields)[i].type);
// change the qualifier of the return type, not of the structure field
// as the structure definition is shared between various structures.
......@@ -420,36 +404,30 @@ postfix_expression
}
} else {
parseContext.error($2.line, " no such field in structure", $3.string->c_str(), "");
parseContext.recover();
$$ = $1;
}
}
} else {
parseContext.error($2.line, " dot operator requires structure, array, vector, or matrix on left hand side", $3.string->c_str(), "");
parseContext.recover();
$$ = $1;
}
// don't delete $3.string, it's from the pool
}
| postfix_expression INC_OP {
parseContext.variableErrorCheck($1);
if (parseContext.lValueErrorCheck($2.line, "++", $1))
parseContext.recover();
parseContext.variableCheck($1);
parseContext.lValueErrorCheck($2.line, "++", $1);
$$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line);
if ($$ == 0) {
parseContext.unaryOpError($2.line, "++", $1->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
| postfix_expression DEC_OP {
parseContext.variableErrorCheck($1);
if (parseContext.lValueErrorCheck($2.line, "--", $1))
parseContext.recover();
parseContext.variableCheck($1);
parseContext.lValueErrorCheck($2.line, "--", $1);
$$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line);
if ($$ == 0) {
parseContext.unaryOpError($2.line, "--", $1->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -457,8 +435,7 @@ postfix_expression
integer_expression
: expression {
if (parseContext.integerErrorCheck($1, "[]"))
parseContext.recover();
parseContext.integerCheck($1, "[]");
$$ = $1;
}
;
......@@ -472,7 +449,6 @@ function_call
int length;
if ($1.intermNode->getAsTyped() == 0 || ! $1.intermNode->getAsTyped()->getType().isArray() || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) {
parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
parseContext.recover();
length = 1;
} else
length = $1.intermNode->getAsTyped()->getType().getArraySize();
......@@ -487,19 +463,19 @@ function_call
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid); // use this to get the type back
if (parseContext.constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
if (parseContext.constructorError($1.line, $1.intermNode, *fnCall, op, &type)) {
$$ = 0;
} else {
//
// It's a constructor, of type 'type'.
//
$$ = parseContext.addConstructor($1.intermNode, type, op, fnCall, $1.line);
if ($$ == 0)
parseContext.error($1.line, "cannot construct with these arguments", type.getCompleteString().c_str(), "");
}
if ($$ == 0) {
parseContext.recover();
if ($$ == 0)
$$ = parseContext.intermediate.setAggregateOperator(0, op, type, $1.line);
}
} else {
//
// Not a constructor. Find it in the symbol table.
......@@ -538,10 +514,8 @@ function_call
for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
qual = (*fnCandidate)[i].type->getQualifier().storage;
if (qual == EvqOut || qual == EvqInOut) {
if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) {
if (parseContext.lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped()))
parseContext.error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
parseContext.recover();
}
}
qualifierList.push_back(qual);
}
......@@ -557,7 +531,6 @@ function_call
constUnion *unionArray = new constUnion[1];
unionArray->setDConst(0.0);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
parseContext.recover();
}
}
delete fnCall;
......@@ -743,7 +716,6 @@ function_identifier
}
if (op == EOpNull) {
parseContext.error($1.line, "cannot construct this type", TType::getBasicString($1.basicType), "");
parseContext.recover();
$1.basicType = EbtFloat;
op = EOpConstructFloat;
}
......@@ -765,21 +737,16 @@ function_identifier
if (method->getObject()->isArray()) {
$$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength);
$$.intermNode = method->getObject();
} else {
} else
parseContext.error(method->getLine(), "only arrays have methods", "", "");
parseContext.recover();
}
} else {
TIntermSymbol* symbol = $1->getAsSymbolNode();
if (symbol) {
if (parseContext.reservedErrorCheck(symbol->getLine(), symbol->getSymbol()))
parseContext.recover();
parseContext.reservedErrorCheck(symbol->getLine(), symbol->getSymbol());
TFunction *function = new TFunction(&symbol->getSymbol(), TType(EbtVoid));
$$.function = function;
} else {
} else
parseContext.error($1->getLine(), "function call, method or subroutine call expected", "", "");
parseContext.recover();
}
}
if ($$.function == 0) {
......@@ -792,26 +759,22 @@ function_identifier
unary_expression
: postfix_expression {
parseContext.variableErrorCheck($1);
parseContext.variableCheck($1);
$$ = $1;
}
| INC_OP unary_expression {
if (parseContext.lValueErrorCheck($1.line, "++", $2))
parseContext.recover();
parseContext.lValueErrorCheck($1.line, "++", $2);
$$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line);
if ($$ == 0) {
parseContext.unaryOpError($1.line, "++", $2->getCompleteString());
parseContext.recover();
$$ = $2;
}
}
| DEC_OP unary_expression {
if (parseContext.lValueErrorCheck($1.line, "--", $2))
parseContext.recover();
parseContext.lValueErrorCheck($1.line, "--", $2);
$$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line);
if ($$ == 0) {
parseContext.unaryOpError($1.line, "--", $2->getCompleteString());
parseContext.recover();
$$ = $2;
}
}
......@@ -827,7 +790,6 @@ unary_expression
default: break; // some compilers want this
}
parseContext.unaryOpError($1.line, errorOp, $2->getCompleteString());
parseContext.recover();
$$ = $2;
}
} else
......@@ -850,7 +812,6 @@ multiplicative_expression
$$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -858,7 +819,6 @@ multiplicative_expression
$$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -866,7 +826,6 @@ multiplicative_expression
$$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -878,7 +837,6 @@ additive_expression
$$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -886,7 +844,6 @@ additive_expression
$$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -899,7 +856,6 @@ shift_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -908,7 +864,6 @@ shift_expression
$$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -920,7 +875,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -930,7 +884,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -940,7 +893,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -950,7 +902,6 @@ relational_expression
$$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -964,7 +915,6 @@ equality_expression
$$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -975,7 +925,6 @@ equality_expression
$$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -991,7 +940,6 @@ and_expression
$$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -1004,7 +952,6 @@ exclusive_or_expression
$$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -1017,7 +964,6 @@ inclusive_or_expression
$$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
}
}
......@@ -1029,7 +975,6 @@ logical_and_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -1043,7 +988,6 @@ logical_xor_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -1057,7 +1001,6 @@ logical_or_expression
$$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
constUnion *unionArray = new constUnion[1];
unionArray->setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
......@@ -1068,13 +1011,11 @@ logical_or_expression
conditional_expression
: logical_or_expression { $$ = $1; }
| logical_or_expression QUESTION expression COLON assignment_expression {
if (parseContext.boolErrorCheck($2.line, $1))
parseContext.recover();
parseContext.boolCheck($2.line, $1);
$$ = parseContext.intermediate.addSelection($1, $3, $5, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, ":", $3->getCompleteString(), $5->getCompleteString());
parseContext.recover();
$$ = $5;
}
}
......@@ -1083,12 +1024,10 @@ conditional_expression
assignment_expression
: conditional_expression { $$ = $1; }
| unary_expression assignment_operator assignment_expression {
if (parseContext.lValueErrorCheck($2.line, "assign", $1))
parseContext.recover();
parseContext.lValueErrorCheck($2.line, "assign", $1);
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.line);
if ($$ == 0) {
parseContext.assignError($2.line, "assign", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $1;
} else if (($1->isArray() || $3->isArray()))
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "=");
......@@ -1132,7 +1071,6 @@ expression
$$ = parseContext.intermediate.addComma($1, $3, $2.line);
if ($$ == 0) {
parseContext.binaryOpError($2.line, ",", $1->getCompleteString(), $3->getCompleteString());
parseContext.recover();
$$ = $3;
}
}
......@@ -1140,8 +1078,7 @@ expression
constant_expression
: conditional_expression {
if (parseContext.constErrorCheck($1))
parseContext.recover();
parseContext.constCheck($1);
$$ = $1;
}
;
......@@ -1224,14 +1161,10 @@ function_prototype
if (prevDec) {
if (prevDec->getReturnType() != $1->getReturnType()) {
parseContext.error($2.line, "overloaded functions must have the same return type", $1->getReturnType().getCompleteTypeString().c_str(), "");
parseContext.recover();
}
for (int i = 0; i < prevDec->getParamCount(); ++i) {
if ((*prevDec)[i].type->getQualifier().storage != (*$1)[i].type->getQualifier().storage) {
parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers",
(*$1)[i].type->getStorageQualifierString(), "");
parseContext.recover();
}
if ((*prevDec)[i].type->getQualifier().storage != (*$1)[i].type->getQualifier().storage)
parseContext.error($2.line, "overloaded functions must have the same parameter qualifiers", (*$1)[i].type->getStorageQualifierString(), "");
}
}
......@@ -1243,10 +1176,8 @@ function_prototype
$$.function = $1;
$$.line = $2.line;
if (! parseContext.symbolTable.insert(*$$.function)) {
if (! parseContext.symbolTable.insert(*$$.function))
parseContext.error($2.line, "illegal redeclaration", $$.function->getName().c_str(), "");
parseContext.recover();
}
}
;
......@@ -1279,7 +1210,6 @@ function_header_with_parameters
// This parameter > first is void
//
parseContext.error($2.line, "cannot be an argument type except for '(void)'", "void", "");
parseContext.recover();
delete $3.param.type;
} else {
// Add the parameter
......@@ -1294,7 +1224,6 @@ function_header
if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) {
parseContext.error($2.line, "no qualifiers allowed for function return",
getStorageQualifierString($1.qualifier.storage), "");
parseContext.recover();
}
// Add the function as a prototype after parsing it (we do not support recursion)
......@@ -1314,10 +1243,8 @@ parameter_declarator
}
if ($1.basicType == EbtVoid) {
parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");
parseContext.recover();
}
if (parseContext.reservedErrorCheck($2.line, *$2.string))
parseContext.recover();
parseContext.reservedErrorCheck($2.line, *$2.string);
TParameter param = {$2.string, new TType($1)};
$$.line = $2.line;
......@@ -1329,11 +1256,8 @@ parameter_declarator
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");
}
if (parseContext.arraySizeRequiredErrorCheck($3.line, $3.arraySizes->front()))
parseContext.recover();
if (parseContext.reservedErrorCheck($2.line, *$2.string))
parseContext.recover();
parseContext.arraySizeRequiredCheck($3.line, $3.arraySizes->front());
parseContext.reservedErrorCheck($2.line, *$2.string);
$1.arraySizes = $3.arraySizes;
......@@ -1352,18 +1276,14 @@ parameter_declaration
if ($1.qualifier.precision != EpqNone)
$$.param.type->getQualifier().precision = $1.qualifier.precision;
if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type))
parseContext.recover();
if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type))
parseContext.recover();
parseContext.parameterSamplerCheck($2.line, $1.qualifier.storage, *$$.param.type);
parseContext.paramCheck($1.line, $1.qualifier.storage, $$.param.type);
}
| parameter_declarator {
$$ = $1;
if (parseContext.parameterSamplerErrorCheck($1.line, EvqIn, *$1.param.type))
parseContext.recover();
if (parseContext.paramErrorCheck($1.line, EvqTemporary, $$.param.type))
parseContext.recover();
parseContext.parameterSamplerCheck($1.line, EvqIn, *$1.param.type);
parseContext.paramCheck($1.line, EvqTemporary, $$.param.type);
}
//
// Without name
......@@ -1373,18 +1293,14 @@ parameter_declaration
if ($1.qualifier.precision != EpqNone)
$$.param.type->getQualifier().precision = $1.qualifier.precision;
if (parseContext.parameterSamplerErrorCheck($2.line, $1.qualifier.storage, *$$.param.type))
parseContext.recover();
if (parseContext.paramErrorCheck($1.line, $1.qualifier.storage, $$.param.type))
parseContext.recover();
parseContext.parameterSamplerCheck($2.line, $1.qualifier.storage, *$$.param.type);
parseContext.paramCheck($1.line, $1.qualifier.storage, $$.param.type);
}
| parameter_type_specifier {
$$ = $1;
if (parseContext.parameterSamplerErrorCheck($1.line, EvqIn, *$1.param.type))
parseContext.recover();
if (parseContext.paramErrorCheck($1.line, EvqTemporary, $$.param.type))
parseContext.recover();
parseContext.parameterSamplerCheck($1.line, EvqIn, *$1.param.type);
parseContext.paramCheck($1.line, EvqTemporary, $$.param.type);
}
;
......@@ -1401,43 +1317,33 @@ init_declarator_list
}
| init_declarator_list COMMA IDENTIFIER {
$$ = $1;
if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $$.type))
parseContext.recover();
if (parseContext.nonInitErrorCheck($3.line, *$3.string, $$.type))
parseContext.recover();
parseContext.nonInitConstCheck($3.line, *$3.string, $$.type);
parseContext.nonInitCheck($3.line, *$3.string, $$.type);
}
| init_declarator_list COMMA IDENTIFIER array_specifier {
if (parseContext.nonInitConstErrorCheck($3.line, *$3.string, $1.type))
parseContext.recover();
parseContext.nonInitConstCheck($3.line, *$3.string, $1.type);
$$ = $1;
if (parseContext.arrayQualifierErrorCheck($4.line, $1.type))
parseContext.recover();
else {
if (! parseContext.arrayQualifierError($4.line, $1.type)) {
$1.type.arraySizes = $4.arraySizes;
TVariable* variable;
if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
parseContext.recover();
parseContext.arrayCheck($4.line, *$3.string, $1.type, variable);
}
}
| init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer {
$$ = $1;
TVariable* variable = 0;
if (parseContext.arrayQualifierErrorCheck($4.line, $1.type))
parseContext.recover();
else {
if (! parseContext.arrayQualifierError($4.line, $1.type)) {
$1.type.arraySizes = $4.arraySizes;
if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))
parseContext.recover();
parseContext.arrayCheck($4.line, *$3.string, $1.type, variable);
}
parseContext.profileRequires($5.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
TIntermNode* intermNode;
if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $6, intermNode, variable)) {
if (! parseContext.executeInitializerError($3.line, *$3.string, $1.type, $6, intermNode, variable)) {
//
// build the intermediate representation
//
......@@ -1445,16 +1351,14 @@ init_declarator_list
$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $5.line);
else
$$.intermAggregate = $1.intermAggregate;
} else {
parseContext.recover();
} else
$$.intermAggregate = 0;
}
}
| init_declarator_list COMMA IDENTIFIER EQUAL initializer {
$$ = $1;
TIntermNode* intermNode;
if (!parseContext.executeInitializer($3.line, *$3.string, $1.type, $5, intermNode)) {
if (!parseContext.executeInitializerError($3.line, *$3.string, $1.type, $5, intermNode)) {
//
// build the intermediate representation
//
......@@ -1462,10 +1366,8 @@ init_declarator_list
$$.intermAggregate = parseContext.intermediate.growAggregate($1.intermNode, intermNode, $4.line);
else
$$.intermAggregate = $1.intermAggregate;
} else {
parseContext.recover();
} else
$$.intermAggregate = 0;
}
}
;
......@@ -1479,28 +1381,21 @@ single_declaration
$$.intermAggregate = 0;
$$.type = $1;
if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $$.type))
parseContext.recover();
if (parseContext.nonInitErrorCheck($2.line, *$2.string, $$.type))
parseContext.recover();
parseContext.nonInitConstCheck($2.line, *$2.string, $$.type);
parseContext.nonInitCheck($2.line, *$2.string, $$.type);
parseContext.updateDefaults($2.line, $$.type, $2.string);
}
| fully_specified_type IDENTIFIER array_specifier {
$$.intermAggregate = 0;
if (parseContext.nonInitConstErrorCheck($2.line, *$2.string, $1))
parseContext.recover();
parseContext.nonInitConstCheck($2.line, *$2.string, $1);
$$.type = $1;
if (parseContext.arrayQualifierErrorCheck($3.line, $1))
parseContext.recover();
else {
if (! parseContext.arrayQualifierError($3.line, $1)) {
$1.arraySizes = $3.arraySizes;
TVariable* variable;
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
parseContext.recover();
parseContext.arrayCheck($3.line, *$2.string, $1, variable);
}
parseContext.updateDefaults($2.line, $$.type, $2.string);
}
......@@ -1509,18 +1404,15 @@ single_declaration
$$.type = $1;
TVariable* variable = 0;
if (parseContext.arrayQualifierErrorCheck($3.line, $1))
parseContext.recover();
else {
if (! parseContext.arrayQualifierError($3.line, $1)) {
$1.arraySizes = $3.arraySizes;
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))
parseContext.recover();
parseContext.arrayCheck($3.line, *$2.string, $1, variable);
}
parseContext.profileRequires($4.line, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
TIntermNode* intermNode;
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $5, intermNode, variable)) {
if (!parseContext.executeInitializerError($2.line, *$2.string, $1, $5, intermNode, variable)) {
//
// Build intermediate representation
//
......@@ -1528,16 +1420,14 @@ single_declaration
$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $4.line);
else
$$.intermAggregate = 0;
} else {
parseContext.recover();
} else
$$.intermAggregate = 0;
}
}
| fully_specified_type IDENTIFIER EQUAL initializer {
$$.type = $1;
TIntermNode* intermNode;
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
if (!parseContext.executeInitializerError($2.line, *$2.string, $1, $4, intermNode)) {
//
// Build intermediate representation
//
......@@ -1545,10 +1435,8 @@ single_declaration
$$.intermAggregate = parseContext.intermediate.makeAggregate(intermNode, $3.line);
else
$$.intermAggregate = 0;
} else {
parseContext.recover();
} else
$$.intermAggregate = 0;
}
}
// Grammar Note: No 'enum', or 'typedef'.
......@@ -1563,21 +1451,17 @@ fully_specified_type
}
}
| type_qualifier type_specifier {
if (parseContext.globalQualifierFixAndErrorCheck($1.line, $1.qualifier, $2))
parseContext.recover();
parseContext.globalQualifierFix($1.line, $1.qualifier, $2);
if ($2.arraySizes) {
parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");
}
if ($2.arraySizes && parseContext.arrayQualifierErrorCheck($2.line, $1)) {
parseContext.recover();
if ($2.arraySizes && parseContext.arrayQualifierError($2.line, $1))
$2.arraySizes = 0;
}
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))
parseContext.recover();
parseContext.mergeQualifiers($2.line, $2, $1, true);
$$ = $2;
......@@ -1596,24 +1480,21 @@ invariant_qualifier
interpolation_qualifier
: SMOOTH {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "smooth"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "smooth");
parseContext.profileRequires($1.line, ENoProfile, 130, 0, "smooth");
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "smooth");
$$.init($1.line);
$$.qualifier.smooth = true;
}
| FLAT {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "flat"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "flat");
parseContext.profileRequires($1.line, ENoProfile, 130, 0, "flat");
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "flat");
$$.init($1.line);
$$.qualifier.flat = true;
}
| NOPERSPECTIVE {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "noperspective"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "noperspective");
parseContext.requireProfile($1.line, static_cast<EProfileMask>(~EEsProfileMask), "noperspective");
parseContext.profileRequires($1.line, ENoProfile, 130, 0, "noperspective");
$$.init($1.line);
......@@ -1667,8 +1548,7 @@ type_qualifier
if ($$.basicType == EbtVoid)
$$.basicType = $2.basicType;
if (parseContext.mergeQualifiersErrorCheck($$.line, $$, $2, false))
parseContext.recover();
parseContext.mergeQualifiers($$.line, $$, $2, false);
}
;
......@@ -1708,8 +1588,7 @@ storage_qualifier
parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "attribute");
parseContext.requireNotRemoved($1.line, EEsProfile, 300, "attribute");
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "attribute");
$$.init($1.line);
$$.qualifier.storage = EvqVaryingIn;
......@@ -1720,8 +1599,7 @@ storage_qualifier
parseContext.requireNotRemoved($1.line, ECoreProfile, 420, "varying");
parseContext.requireNotRemoved($1.line, EEsProfile, 300, "varying");
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "varying");
$$.init($1.line);
if (parseContext.language == EShLangVertex)
......@@ -1730,52 +1608,44 @@ storage_qualifier
$$.qualifier.storage = EvqVaryingIn;
}
| INOUT {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out");
$$.init($1.line);
$$.qualifier.storage = EvqInOut;
}
| IN {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "in"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "in");
$$.init($1.line);
$$.qualifier.storage = EvqIn;
}
| OUT {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "out");
$$.init($1.line);
$$.qualifier.storage = EvqOut;
}
| CENTROID {
parseContext.profileRequires($1.line, ENoProfile, 120, 0, "centroid");
parseContext.profileRequires($1.line, EEsProfile, 300, 0, "centroid");
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "centroid"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "centroid");
$$.init($1.line);
$$.qualifier.centroid = true;
}
| PATCH {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "patch"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "patch");
$$.init($1.line);
$$.qualifier.patch = true;
}
| SAMPLE {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "sample"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "sample");
$$.init($1.line);
$$.qualifier.sample = true;
}
| UNIFORM {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "uniform");
$$.init($1.line);
$$.qualifier.storage = EvqUniform;
}
| BUFFER {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "buffer"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "buffer");
$$.init($1.line);
$$.qualifier.storage = EvqUniform; // TODO: 4.0 functionality: implement BUFFER
}
......@@ -1807,14 +1677,12 @@ storage_qualifier
$$.qualifier.writeonly = true;
}
| SUBROUTINE {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine");
$$.init($1.line);
$$.qualifier.storage = EvqUniform;
}
| SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN {
if (parseContext.globalErrorCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine"))
parseContext.recover();
parseContext.globalCheck($1.line, parseContext.symbolTable.atGlobalLevel(), "subroutine");
$$.init($1.line);
$$.qualifier.storage = EvqUniform;
// TODO: 4.0 semantics: subroutines
......@@ -1854,8 +1722,7 @@ array_specifier
$$.arraySizes = NewPoolTArraySizes();
int size;
if (parseContext.arraySizeErrorCheck($2->getLine(), $2, size))
parseContext.recover();
parseContext.arraySizeCheck($2->getLine(), $2, size);
$$.arraySizes->push_back(size);
}
| array_specifier LEFT_BRACKET RIGHT_BRACKET {
......@@ -1866,8 +1733,7 @@ array_specifier
$$ = $1;
int size;
if (parseContext.arraySizeErrorCheck($3->getLine(), $3, size))
parseContext.recover();
parseContext.arraySizeCheck($3->getLine(), $3, size);
$$.arraySizes->push_back(size);
}
;
......@@ -2504,10 +2370,8 @@ type_specifier_nonarray
$$.init($1.line, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtStruct;
$$.userDef = &structure;
} else {
} else
parseContext.error($1.line, "expected type name", $1.string->c_str(), "");
parseContext.recover();
}
}
;
......@@ -2541,10 +2405,8 @@ struct_specifier
TType* structure = new TType($4, *$2.string);
TVariable* userTypeDef = new TVariable($2.string, *structure, true);
if (! parseContext.symbolTable.insert(*userTypeDef)) {
if (! parseContext.symbolTable.insert(*userTypeDef))
parseContext.error($2.line, "redefinition", $2.string->c_str(), "struct");
parseContext.recover();
}
$$.init($1.line);
$$.basicType = EbtStruct;
$$.userDef = structure;
......@@ -2565,10 +2427,8 @@ struct_declaration_list
$$ = $1;
for (unsigned int i = 0; i < $2->size(); ++i) {
for (unsigned int j = 0; j < $$->size(); ++j) {
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) {
if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName())
parseContext.error((*$2)[i].line, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str());
parseContext.recover();
}
}
$$->push_back((*$2)[i]);
}
......@@ -2584,9 +2444,8 @@ struct_declaration
$$ = $2;
if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {
parseContext.recover();
}
parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1);
for (unsigned int i = 0; i < $$->size(); ++i)
(*$$)[i].type->mergeType($1);
}
......@@ -2598,10 +2457,9 @@ struct_declaration
$$ = $3;
if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2))
parseContext.recover();
if (parseContext.mergeQualifiersErrorCheck($2.line, $2, $1, true))
parseContext.recover();
parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2);
parseContext.mergeQualifiers($2.line, $2, $1, true);
for (unsigned int i = 0; i < $$->size(); ++i)
(*$$)[i].type->mergeType($2);
}
......@@ -2728,8 +2586,7 @@ expression_statement
selection_statement
: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
if (parseContext.boolErrorCheck($1.line, $3))
parseContext.recover();
parseContext.boolCheck($1.line, $3);
$$ = parseContext.intermediate.addSelection($3, $5, $1.line);
}
;
......@@ -2749,20 +2606,16 @@ condition
// In 1996 c++ draft, conditions can include single declarations
: expression {
$$ = $1;
if (parseContext.boolErrorCheck($1->getLine(), $1))
parseContext.recover();
parseContext.boolCheck($1->getLine(), $1);
}
| fully_specified_type IDENTIFIER EQUAL initializer {
TIntermNode* intermNode;
if (parseContext.boolErrorCheck($2.line, $1))
parseContext.recover();
parseContext.boolCheck($2.line, $1);
if (!parseContext.executeInitializer($2.line, *$2.string, $1, $4, intermNode))
$$ = $4;
else {
parseContext.recover();
if (parseContext.executeInitializerError($2.line, *$2.string, $1, $4, intermNode))
$$ = 0;
}
else
$$ = $4;
}
;
......@@ -2807,8 +2660,7 @@ iteration_statement
--parseContext.loopNestingLevel;
}
| DO { ++parseContext.loopNestingLevel; } statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
if (parseContext.boolErrorCheck($8.line, $6))
parseContext.recover();
parseContext.boolCheck($8.line, $6);
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.line);
--parseContext.loopNestingLevel;
......@@ -2860,36 +2712,27 @@ for_rest_statement
jump_statement
: CONTINUE SEMICOLON {
if (parseContext.loopNestingLevel <= 0) {
if (parseContext.loopNestingLevel <= 0)
parseContext.error($1.line, "continue statement only allowed in loops", "", "");
parseContext.recover();
}
$$ = parseContext.intermediate.addBranch(EOpContinue, $1.line);
}
| BREAK SEMICOLON {
if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) {
if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0)
parseContext.error($1.line, "break statement only allowed in switch and loops", "", "");
parseContext.recover();
}
$$ = parseContext.intermediate.addBranch(EOpBreak, $1.line);
}
| RETURN SEMICOLON {
$$ = parseContext.intermediate.addBranch(EOpReturn, $1.line);
if (parseContext.currentFunctionType->getBasicType() != EbtVoid) {
if (parseContext.currentFunctionType->getBasicType() != EbtVoid)
parseContext.error($1.line, "non-void function must return a value", "return", "");
parseContext.recover();
}
}
| RETURN expression SEMICOLON {
$$ = parseContext.intermediate.addBranch(EOpReturn, $2, $1.line);
parseContext.functionReturnsValue = true;
if (parseContext.currentFunctionType->getBasicType() == EbtVoid) {
if (parseContext.currentFunctionType->getBasicType() == EbtVoid)
parseContext.error($1.line, "void function cannot return a value", "return", "");
parseContext.recover();
} else if (*(parseContext.currentFunctionType) != $2->getType()) {
else if (*(parseContext.currentFunctionType) != $2->getType())
parseContext.error($1.line, "function return is not matching type:", "return", "");
parseContext.recover();
}
}
| DISCARD SEMICOLON {
parseContext.requireStage($1.line, EShLangFragmentMask, "discard");
......@@ -2925,10 +2768,8 @@ function_definition
TSymbol* symbol = parseContext.symbolTable.find(function.getMangledName());
TFunction* prevDec = symbol ? symbol->getAsFunction() : 0;
if (! prevDec) {
if (! prevDec)
parseContext.error($1.line, "can't find function name", function.getName().c_str(), "");
parseContext.recover();
}
//
// Note: 'prevDec' could be 'function' if this is the first time we've seen function
......@@ -2940,7 +2781,6 @@ function_definition
// Then this function already has a body.
//
parseContext.error($1.line, "function already has a body", function.getName().c_str(), "");
parseContext.recover();
}
if (prevDec) {
prevDec->setDefined();
......@@ -2956,14 +2796,10 @@ function_definition
// Raise error message if main function takes any parameters or return anything other than void
//
if (function.getName() == "main") {
if (function.getParamCount() > 0) {
if (function.getParamCount() > 0)
parseContext.error($1.line, "function cannot take any parameter(s)", function.getName().c_str(), "");
parseContext.recover();
}
if (function.getReturnType().getBasicType() != EbtVoid) {
if (function.getReturnType().getBasicType() != EbtVoid)
parseContext.error($1.line, "", function.getReturnType().getCompleteTypeString().c_str(), "main function cannot return a value");
parseContext.recover();
}
}
//
......@@ -2989,7 +2825,6 @@ function_definition
//
if (! parseContext.symbolTable.insert(*variable)) {
parseContext.error($1.line, "redefinition", variable->getName().c_str(), "");
parseContext.recover();
delete variable;
}
//
......@@ -3016,10 +2851,8 @@ function_definition
}
compound_statement_no_new_scope {
// May be best done as post process phase on intermediate code
if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) {
if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue)
parseContext.error($1.line, "function does not return a value:", "", $1.function->getName().c_str());
parseContext.recover();
}
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
$$ = parseContext.intermediate.growAggregate($1.intermAggregate, $3, 0);
parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getReturnType(), $1.line);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment