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
This commit is contained in:
John Kessenich 2013-06-12 22:41:21 +00:00
parent fbe01520b6
commit fd8e101072
5 changed files with 227 additions and 518 deletions

View file

@ -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;
}

View file

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

View file

@ -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();
}
}
}

View file

@ -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

File diff suppressed because it is too large Load diff