Commit 856c497e by Olli Etuaho Committed by Commit Bot

Clarify error checking function names in the GLSL parser

Most error checking functions in ParseContext used to follow a format like <property>ErrorCheck. Sometimes this function would check that the node/value would have <property>, sometimes it would check that the node/value would not have it, which was confusing. Change most of these functions to use a lot more descriptive names, which clearly communicate what they are checking for. Also includes a bit of refactoring in constructorErrorCheck(), so that the function only checks for errors rather than also setting the type of the constructor node. Also make TType::arraySize unsigned, and return a sanitized size from checkIsValidArraySize() instead of using an output parameter. BUG=angleproject:911 TEST=angle_unittests Change-Id: Id9767b8c79594ad3f782f801ea68eb96df721a31 Reviewed-on: https://chromium-review.googlesource.com/367070Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 9371f7ab
...@@ -153,7 +153,7 @@ class TIntermTyped : public TIntermNode ...@@ -153,7 +153,7 @@ class TIntermTyped : public TIntermNode
const char *getBasicString() const { return mType.getBasicString(); } const char *getBasicString() const { return mType.getBasicString(); }
TString getCompleteString() const { return mType.getCompleteString(); } TString getCompleteString() const { return mType.getCompleteString(); }
int getArraySize() const { return mType.getArraySize(); } unsigned int getArraySize() const { return mType.getArraySize(); }
bool isConstructorWithOnlyConstantUnionParameters(); bool isConstructorWithOnlyConstantUnionParameters();
......
...@@ -357,7 +357,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -357,7 +357,7 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
if (left->isArray()) if (left->isArray())
{ {
// The shader will fail validation if the array length is not > 0. // The shader will fail validation if the array length is not > 0.
maxSize = leftType.getArraySize() - 1; maxSize = static_cast<int>(leftType.getArraySize()) - 1;
} }
else else
{ {
......
...@@ -224,7 +224,7 @@ const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() c ...@@ -224,7 +224,7 @@ const std::map<std::string, unsigned int> &OutputHLSL::getUniformRegisterMap() c
int OutputHLSL::vectorSize(const TType &type) const int OutputHLSL::vectorSize(const TType &type) const
{ {
int elementSize = type.isMatrix() ? type.getCols() : 1; int elementSize = type.isMatrix() ? type.getCols() : 1;
int arraySize = type.isArray() ? type.getArraySize() : 1; unsigned int arraySize = type.isArray() ? type.getArraySize() : 1u;
return elementSize * arraySize; return elementSize * arraySize;
} }
...@@ -1711,7 +1711,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1711,7 +1711,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
TVector<TIntermSymbol *> samplerSymbols; TVector<TIntermSymbol *> samplerSymbols;
TString structName = samplerNamePrefixFromStruct(typedArg); TString structName = samplerNamePrefixFromStruct(typedArg);
argType.createSamplerSymbols("angle_" + structName, "", argType.createSamplerSymbols("angle_" + structName, "",
argType.isArray() ? argType.getArraySize() : 0, argType.isArray() ? argType.getArraySize() : 0u,
&samplerSymbols, nullptr); &samplerSymbols, nullptr);
for (const TIntermSymbol *sampler : samplerSymbols) for (const TIntermSymbol *sampler : samplerSymbols)
{ {
...@@ -2502,7 +2502,7 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol) ...@@ -2502,7 +2502,7 @@ TString OutputHLSL::argumentString(const TIntermSymbol *symbol)
{ {
ASSERT(qualifier != EvqOut && qualifier != EvqInOut); ASSERT(qualifier != EvqOut && qualifier != EvqInOut);
TVector<TIntermSymbol *> samplerSymbols; TVector<TIntermSymbol *> samplerSymbols;
type.createSamplerSymbols("angle" + nameStr, "", 0, &samplerSymbols, nullptr); type.createSamplerSymbols("angle" + nameStr, "", 0u, &samplerSymbols, nullptr);
for (const TIntermSymbol *sampler : samplerSymbols) for (const TIntermSymbol *sampler : samplerSymbols)
{ {
if (mOutputType == SH_HLSL_4_1_OUTPUT) if (mOutputType == SH_HLSL_4_1_OUTPUT)
...@@ -2870,14 +2870,14 @@ TString OutputHLSL::addArrayConstructIntoFunction(const TType& type) ...@@ -2870,14 +2870,14 @@ TString OutputHLSL::addArrayConstructIntoFunction(const TType& type)
fnOut << "void " << function.functionName << "(out " fnOut << "void " << function.functionName << "(out "
<< typeName << " a[" << type.getArraySize() << "]"; << typeName << " a[" << type.getArraySize() << "]";
for (int i = 0; i < type.getArraySize(); ++i) for (unsigned int i = 0u; i < type.getArraySize(); ++i)
{ {
fnOut << ", " << typeName << " b" << i; fnOut << ", " << typeName << " b" << i;
} }
fnOut << ")\n" fnOut << ")\n"
"{\n"; "{\n";
for (int i = 0; i < type.getArraySize(); ++i) for (unsigned int i = 0u; i < type.getArraySize(); ++i)
{ {
fnOut << " a[" << i << "] = b" << i << ";\n"; fnOut << " a[" << i << "] = b" << i << ";\n";
} }
......
...@@ -213,9 +213,9 @@ void TParseContext::binaryOpError(const TSourceLoc &line, ...@@ -213,9 +213,9 @@ void TParseContext::binaryOpError(const TSourceLoc &line,
error(line, " wrong operand types ", op, extraInfo.c_str()); error(line, " wrong operand types ", op, extraInfo.c_str());
} }
void TParseContext::precisionErrorCheck(const TSourceLoc &line, void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
TPrecision precision, TPrecision precision,
TBasicType type) TBasicType type)
{ {
if (!mChecksPrecisionErrors) if (!mChecksPrecisionErrors)
return; return;
...@@ -247,7 +247,7 @@ void TParseContext::precisionErrorCheck(const TSourceLoc &line, ...@@ -247,7 +247,7 @@ void TParseContext::precisionErrorCheck(const TSourceLoc &line,
// //
// Returns true if the was an error. // Returns true if the was an error.
// //
bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped *node) bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
{ {
TIntermSymbol *symNode = node->getAsSymbolNode(); TIntermSymbol *symNode = node->getAsSymbolNode();
TIntermBinary *binaryNode = node->getAsBinaryNode(); TIntermBinary *binaryNode = node->getAsBinaryNode();
...@@ -262,9 +262,9 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn ...@@ -262,9 +262,9 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn
case EOpIndexIndirect: case EOpIndexIndirect:
case EOpIndexDirectStruct: case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock: case EOpIndexDirectInterfaceBlock:
return lValueErrorCheck(line, op, binaryNode->getLeft()); return checkCanBeLValue(line, op, binaryNode->getLeft());
case EOpVectorSwizzle: case EOpVectorSwizzle:
errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); errorReturn = checkCanBeLValue(line, op, binaryNode->getLeft());
if (!errorReturn) if (!errorReturn)
{ {
int offset[4] = {0, 0, 0, 0}; int offset[4] = {0, 0, 0, 0};
...@@ -403,7 +403,7 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn ...@@ -403,7 +403,7 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc &line, const char *op, TIn
// Both test, and if necessary spit out an error, to see if the node is really // Both test, and if necessary spit out an error, to see if the node is really
// a constant. // a constant.
void TParseContext::constErrorCheck(TIntermTyped *node) void TParseContext::checkIsConst(TIntermTyped *node)
{ {
if (node->getQualifier() != EvqConst) if (node->getQualifier() != EvqConst)
{ {
...@@ -413,7 +413,7 @@ void TParseContext::constErrorCheck(TIntermTyped *node) ...@@ -413,7 +413,7 @@ void TParseContext::constErrorCheck(TIntermTyped *node)
// Both test, and if necessary spit out an error, to see if the node is really // Both test, and if necessary spit out an error, to see if the node is really
// an integer. // an integer.
void TParseContext::integerErrorCheck(TIntermTyped *node, const char *token) void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
{ {
if (!node->isScalarInt()) if (!node->isScalarInt())
{ {
...@@ -423,9 +423,9 @@ void TParseContext::integerErrorCheck(TIntermTyped *node, const char *token) ...@@ -423,9 +423,9 @@ void TParseContext::integerErrorCheck(TIntermTyped *node, const char *token)
// Both test, and if necessary spit out an error, to see if we are currently // Both test, and if necessary spit out an error, to see if we are currently
// globally scoped. // globally scoped.
void TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const char *token) void TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
{ {
if (!global) if (!symbolTable.atGlobalLevel())
{ {
error(line, "only allowed at global scope", token); error(line, "only allowed at global scope", token);
} }
...@@ -439,7 +439,7 @@ void TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const ...@@ -439,7 +439,7 @@ void TParseContext::globalErrorCheck(const TSourceLoc &line, bool global, const
// //
// Returns true if there was an error. // Returns true if there was an error.
// //
bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString &identifier) bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const TString &identifier)
{ {
static const char *reservedErrMsg = "reserved built-in name"; static const char *reservedErrMsg = "reserved built-in name";
if (!symbolTable.atBuiltInLevel()) if (!symbolTable.atBuiltInLevel())
...@@ -487,14 +487,12 @@ bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString &id ...@@ -487,14 +487,12 @@ bool TParseContext::reservedErrorCheck(const TSourceLoc &line, const TString &id
// //
// Returns true if there was an error in construction. // Returns true if there was an error in construction.
// //
bool TParseContext::constructorErrorCheck(const TSourceLoc &line, bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
TIntermNode *argumentsNode, TIntermNode *argumentsNode,
TFunction &function, const TFunction &function,
TOperator op, TOperator op,
TType *type) const TType &type)
{ {
*type = function.getReturnType();
bool constructingMatrix = false; bool constructingMatrix = false;
switch (op) switch (op)
{ {
...@@ -520,7 +518,6 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -520,7 +518,6 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
// //
size_t size = 0; size_t size = 0;
bool constType = true;
bool full = false; bool full = false;
bool overFull = false; bool overFull = false;
bool matrixInMatrix = false; bool matrixInMatrix = false;
...@@ -534,24 +531,17 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -534,24 +531,17 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
matrixInMatrix = true; matrixInMatrix = true;
if (full) if (full)
overFull = true; overFull = true;
if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize()) if (op != EOpConstructStruct && !type.isArray() && size >= type.getObjectSize())
full = true; full = true;
if (param.type->getQualifier() != EvqConst)
constType = false;
if (param.type->isArray()) if (param.type->isArray())
arrayArg = true; arrayArg = true;
} }
if (constType) if (type.isArray())
type->setQualifier(EvqConst);
if (type->isArray())
{ {
if (type->isUnsizedArray()) // The size of an unsized constructor should already have been determined.
{ ASSERT(!type.isUnsizedArray());
type->setArraySize(static_cast<int>(function.getParamCount())); if (static_cast<size_t>(type.getArraySize()) != function.getParamCount())
}
else if (static_cast<size_t>(type->getArraySize()) != function.getParamCount())
{ {
error(line, "array constructor needs one argument per array element", "constructor"); error(line, "array constructor needs one argument per array element", "constructor");
return true; return true;
...@@ -564,7 +554,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -564,7 +554,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
return true; return true;
} }
if (matrixInMatrix && !type->isArray()) if (matrixInMatrix && !type.isArray())
{ {
if (function.getParamCount() != 1) if (function.getParamCount() != 1)
{ {
...@@ -580,8 +570,8 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -580,8 +570,8 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
return true; return true;
} }
if (op == EOpConstructStruct && !type->isArray() && if (op == EOpConstructStruct && !type.isArray() &&
type->getStruct()->fields().size() != function.getParamCount()) type.getStruct()->fields().size() != function.getParamCount())
{ {
error(line, error(line,
"Number of constructor parameters does not match the number of structure fields", "Number of constructor parameters does not match the number of structure fields",
...@@ -589,10 +579,10 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -589,10 +579,10 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
return true; return true;
} }
if (!type->isMatrix() || !matrixInMatrix) if (!type.isMatrix() || !matrixInMatrix)
{ {
if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) || if ((op != EOpConstructStruct && size != 1 && size < type.getObjectSize()) ||
(op == EOpConstructStruct && size < type->getObjectSize())) (op == EOpConstructStruct && size < type.getObjectSize()))
{ {
error(line, "not enough data provided for construction", "constructor"); error(line, "not enough data provided for construction", "constructor");
return true; return true;
...@@ -622,6 +612,38 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -622,6 +612,38 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
} }
} }
if (type.isArray())
{
// GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
// the array.
for (TIntermNode *&argNode : *argumentsAgg->getSequence())
{
const TType &argType = argNode->getAsTyped()->getType();
// It has already been checked that the argument is not an array.
ASSERT(!argType.isArray());
if (!argType.sameElementType(type))
{
error(line, "Array constructor argument has an incorrect type", "Error");
return true;
}
}
}
else if (op == EOpConstructStruct)
{
const TFieldList &fields = type.getStruct()->fields();
TIntermSequence *args = argumentsAgg->getSequence();
for (size_t i = 0; i < fields.size(); i++)
{
if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type())
{
error(line, "Structure constructor arguments do not match structure fields",
"Error");
return true;
}
}
}
return false; return false;
} }
...@@ -630,7 +652,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line, ...@@ -630,7 +652,7 @@ bool TParseContext::constructorErrorCheck(const TSourceLoc &line,
// //
// returns true in case of an error // returns true in case of an error
// //
bool TParseContext::voidErrorCheck(const TSourceLoc &line, bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
const TString &identifier, const TString &identifier,
const TBasicType &type) const TBasicType &type)
{ {
...@@ -645,7 +667,7 @@ bool TParseContext::voidErrorCheck(const TSourceLoc &line, ...@@ -645,7 +667,7 @@ bool TParseContext::voidErrorCheck(const TSourceLoc &line,
// This function checks to see if the node (for the expression) contains a scalar boolean expression // This function checks to see if the node (for the expression) contains a scalar boolean expression
// or not. // or not.
void TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *type) void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
{ {
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
{ {
...@@ -655,7 +677,7 @@ void TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *t ...@@ -655,7 +677,7 @@ void TParseContext::boolErrorCheck(const TSourceLoc &line, const TIntermTyped *t
// This function checks to see if the node (for the expression) contains a scalar boolean expression // This function checks to see if the node (for the expression) contains a scalar boolean expression
// or not. // or not.
void TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pType) void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
{ {
if (pType.type != EbtBool || pType.isAggregate()) if (pType.type != EbtBool || pType.isAggregate())
{ {
...@@ -663,7 +685,7 @@ void TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pT ...@@ -663,7 +685,7 @@ void TParseContext::boolErrorCheck(const TSourceLoc &line, const TPublicType &pT
} }
} }
bool TParseContext::samplerErrorCheck(const TSourceLoc &line, bool TParseContext::checkIsNotSampler(const TSourceLoc &line,
const TPublicType &pType, const TPublicType &pType,
const char *reason) const char *reason)
{ {
...@@ -688,7 +710,8 @@ bool TParseContext::samplerErrorCheck(const TSourceLoc &line, ...@@ -688,7 +710,8 @@ bool TParseContext::samplerErrorCheck(const TSourceLoc &line,
return false; return false;
} }
void TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType) void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
const TPublicType &pType)
{ {
if (pType.layoutQualifier.location != -1) if (pType.layoutQualifier.location != -1)
{ {
...@@ -697,9 +720,19 @@ void TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TP ...@@ -697,9 +720,19 @@ void TParseContext::locationDeclaratorListCheck(const TSourceLoc &line, const TP
} }
} }
void TParseContext::parameterSamplerErrorCheck(const TSourceLoc &line, void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
TQualifier qualifier, const TLayoutQualifier &layoutQualifier)
const TType &type) {
if (layoutQualifier.location != -1)
{
error(location, "invalid layout qualifier:", "location",
"only valid on program inputs and outputs");
}
}
void TParseContext::checkOutParameterIsNotSampler(const TSourceLoc &line,
TQualifier qualifier,
const TType &type)
{ {
if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct && if ((qualifier == EvqOut || qualifier == EvqInOut) && type.getBasicType() != EbtStruct &&
IsSampler(type.getBasicType())) IsSampler(type.getBasicType()))
...@@ -727,7 +760,7 @@ bool TParseContext::containsSampler(const TType &type) ...@@ -727,7 +760,7 @@ bool TParseContext::containsSampler(const TType &type)
} }
// Do size checking for an array type's size. // Do size checking for an array type's size.
void TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size) unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
{ {
TIntermConstantUnion *constant = expr->getAsConstantUnion(); TIntermConstantUnion *constant = expr->getAsConstantUnion();
...@@ -737,36 +770,32 @@ void TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *ex ...@@ -737,36 +770,32 @@ void TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *ex
if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt()) if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
{ {
error(line, "array size must be a constant integer expression", ""); error(line, "array size must be a constant integer expression", "");
size = 1; return 1u;
return;
} }
unsigned int unsignedSize = 0; unsigned int size = 0u;
if (constant->getBasicType() == EbtUInt) if (constant->getBasicType() == EbtUInt)
{ {
unsignedSize = constant->getUConst(0); size = constant->getUConst(0);
size = static_cast<int>(unsignedSize);
} }
else else
{ {
size = constant->getIConst(0); int signedSize = constant->getIConst(0);
if (size < 0) if (signedSize < 0)
{ {
error(line, "array size must be non-negative", ""); error(line, "array size must be non-negative", "");
size = 1; return 1u;
return;
} }
unsignedSize = static_cast<unsigned int>(size); size = static_cast<unsigned int>(signedSize);
} }
if (size == 0) if (size == 0u)
{ {
error(line, "array size must be greater than zero", ""); error(line, "array size must be greater than zero", "");
size = 1; return 1u;
return;
} }
// The size of arrays is restricted here to prevent issues further down the // The size of arrays is restricted here to prevent issues further down the
...@@ -774,19 +803,20 @@ void TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *ex ...@@ -774,19 +803,20 @@ void TParseContext::arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *ex
// 4096 registers so this should be reasonable even for aggressively optimizable code. // 4096 registers so this should be reasonable even for aggressively optimizable code.
const unsigned int sizeLimit = 65536; const unsigned int sizeLimit = 65536;
if (unsignedSize > sizeLimit) if (size > sizeLimit)
{ {
error(line, "array size too large", ""); error(line, "array size too large", "");
size = 1; return 1u;
return;
} }
return size;
} }
// See if this qualifier can be an array. // See if this qualifier can be an array.
// //
// Returns true if there is an error. // Returns true if there is an error.
// //
bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, const TPublicType &type) bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &type)
{ {
if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) ||
(type.qualifier == EvqConst && mShaderVersion < 300)) (type.qualifier == EvqConst && mShaderVersion < 300))
...@@ -803,7 +833,7 @@ bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, const TPubl ...@@ -803,7 +833,7 @@ bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc &line, const TPubl
// //
// Returns true if there is an error. // Returns true if there is an error.
// //
bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, const TPublicType &type) bool TParseContext::checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &type)
{ {
// //
// Can the type be an array? // Can the type be an array?
...@@ -827,9 +857,9 @@ bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, const TPublicTyp ...@@ -827,9 +857,9 @@ bool TParseContext::arrayTypeErrorCheck(const TSourceLoc &line, const TPublicTyp
} }
// Enforce non-initializer type/qualifier rules. // Enforce non-initializer type/qualifier rules.
void TParseContext::nonInitErrorCheck(const TSourceLoc &line, void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
const TString &identifier, const TString &identifier,
TPublicType *type) TPublicType *type)
{ {
ASSERT(type != nullptr); ASSERT(type != nullptr);
if (type->qualifier == EvqConst) if (type->qualifier == EvqConst)
...@@ -870,18 +900,18 @@ bool TParseContext::declareVariable(const TSourceLoc &line, ...@@ -870,18 +900,18 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
{ {
ASSERT((*variable) == nullptr); ASSERT((*variable) == nullptr);
bool needsReservedErrorCheck = true; bool needsReservedCheck = true;
// gl_LastFragData may be redeclared with a new precision qualifier // gl_LastFragData may be redeclared with a new precision qualifier
if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0) if (type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
{ {
const TVariable *maxDrawBuffers = static_cast<const TVariable *>( const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion)); symbolTable.findBuiltIn("gl_MaxDrawBuffers", mShaderVersion));
if (type.getArraySize() == maxDrawBuffers->getConstPointer()->getIConst()) if (static_cast<int>(type.getArraySize()) == maxDrawBuffers->getConstPointer()->getIConst())
{ {
if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion)) if (TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
{ {
needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension()); needsReservedCheck = checkCanUseExtension(line, builtInSymbol->getExtension());
} }
} }
else else
...@@ -892,7 +922,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line, ...@@ -892,7 +922,7 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
} }
} }
if (needsReservedErrorCheck && reservedErrorCheck(line, identifier)) if (needsReservedCheck && checkIsNotReserved(line, identifier))
return false; return false;
(*variable) = new TVariable(&identifier, type); (*variable) = new TVariable(&identifier, type);
...@@ -903,16 +933,16 @@ bool TParseContext::declareVariable(const TSourceLoc &line, ...@@ -903,16 +933,16 @@ bool TParseContext::declareVariable(const TSourceLoc &line,
return false; return false;
} }
if (voidErrorCheck(line, identifier, type.getBasicType())) if (checkIsNonVoid(line, identifier, type.getBasicType()))
return false; return false;
return true; return true;
} }
void TParseContext::paramErrorCheck(const TSourceLoc &line, void TParseContext::checkIsParameterQualifierValid(const TSourceLoc &line,
TQualifier qualifier, TQualifier qualifier,
TQualifier paramQualifier, TQualifier paramQualifier,
TType *type) TType *type)
{ {
if (qualifier != EvqConst && qualifier != EvqTemporary) if (qualifier != EvqConst && qualifier != EvqTemporary)
{ {
...@@ -932,7 +962,7 @@ void TParseContext::paramErrorCheck(const TSourceLoc &line, ...@@ -932,7 +962,7 @@ void TParseContext::paramErrorCheck(const TSourceLoc &line,
type->setQualifier(paramQualifier); type->setQualifier(paramQualifier);
} }
bool TParseContext::extensionErrorCheck(const TSourceLoc &line, const TString &extension) bool TParseContext::checkCanUseExtension(const TSourceLoc &line, const TString &extension)
{ {
const TExtensionBehavior &extBehavior = extensionBehavior(); const TExtensionBehavior &extBehavior = extensionBehavior();
TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str()); TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
...@@ -981,7 +1011,7 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, ...@@ -981,7 +1011,7 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
} }
if (publicType.qualifier != EvqUniform && if (publicType.qualifier != EvqUniform &&
samplerErrorCheck(identifierLocation, publicType, "samplers must be uniform")) checkIsNotSampler(identifierLocation, publicType, "samplers must be uniform"))
{ {
return; return;
} }
...@@ -1007,23 +1037,13 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, ...@@ -1007,23 +1037,13 @@ void TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType,
if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut) if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut)
{ {
layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier); checkLocationIsNotSpecified(identifierLocation, publicType.layoutQualifier);
} }
} }
void TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, void TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
const TLayoutQualifier &layoutQualifier) const TString &layoutQualifierName,
{ int versionRequired)
if (layoutQualifier.location != -1)
{
error(location, "invalid layout qualifier:", "location",
"only valid on program inputs and outputs");
}
}
void TParseContext::layoutSupportedErrorCheck(const TSourceLoc &location,
const TString &layoutQualifierName,
int versionRequired)
{ {
if (mShaderVersion < versionRequired) if (mShaderVersion < versionRequired)
...@@ -1032,8 +1052,8 @@ void TParseContext::layoutSupportedErrorCheck(const TSourceLoc &location, ...@@ -1032,8 +1052,8 @@ void TParseContext::layoutSupportedErrorCheck(const TSourceLoc &location,
} }
} }
bool TParseContext::layoutWorkGroupSizeErrorCheck(const TSourceLoc &location, bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
const TLayoutQualifier &layoutQualifier) const TLayoutQualifier &layoutQualifier)
{ {
const TLocalSize &localSize = layoutQualifier.localSize; const TLocalSize &localSize = layoutQualifier.localSize;
for (size_t i = 0u; i < localSize.size(); ++i) for (size_t i = 0u; i < localSize.size(); ++i)
...@@ -1050,17 +1070,17 @@ bool TParseContext::layoutWorkGroupSizeErrorCheck(const TSourceLoc &location, ...@@ -1050,17 +1070,17 @@ bool TParseContext::layoutWorkGroupSizeErrorCheck(const TSourceLoc &location,
} }
void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
TIntermAggregate *aggregate) TIntermAggregate *fnCall)
{ {
for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
{ {
TQualifier qual = fnCandidate->getParam(i).type->getQualifier(); TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
if (qual == EvqOut || qual == EvqInOut) if (qual == EvqOut || qual == EvqInOut)
{ {
TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped(); TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
if (lValueErrorCheck(node->getLine(), "assign", node)) if (checkCanBeLValue(argument->getLine(), "assign", argument))
{ {
error(node->getLine(), error(argument->getLine(),
"Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
return; return;
} }
...@@ -1068,8 +1088,8 @@ void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, ...@@ -1068,8 +1088,8 @@ void TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate,
} }
} }
void TParseContext::es3InvariantErrorCheck(const TQualifier qualifier, void TParseContext::checkInvariantIsOutVariableES3(const TQualifier qualifier,
const TSourceLoc &invariantLocation) const TSourceLoc &invariantLocation)
{ {
if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut) if (!sh::IsVaryingOut(qualifier) && qualifier != EvqFragmentOut)
{ {
...@@ -1154,7 +1174,7 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, ...@@ -1154,7 +1174,7 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) && if (symbolTable.findBuiltIn(variable->getName(), mShaderVersion) &&
!variable->getExtension().empty()) !variable->getExtension().empty())
{ {
extensionErrorCheck(location, variable->getExtension()); checkCanUseExtension(location, variable->getExtension());
} }
// Reject shaders using both gl_FragData and gl_FragColor // Reject shaders using both gl_FragData and gl_FragColor
...@@ -1386,7 +1406,7 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, ...@@ -1386,7 +1406,7 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
returnType.invariant = invariant; returnType.invariant = invariant;
returnType.layoutQualifier = layoutQualifier; returnType.layoutQualifier = layoutQualifier;
layoutWorkGroupSizeErrorCheck(typeSpecifier.line, layoutQualifier); checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, layoutQualifier);
if (mShaderVersion < 300) if (mShaderVersion < 300)
{ {
...@@ -1412,11 +1432,11 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, ...@@ -1412,11 +1432,11 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
{ {
if (!layoutQualifier.isEmpty()) if (!layoutQualifier.isEmpty())
{ {
globalErrorCheck(typeSpecifier.line, symbolTable.atGlobalLevel(), "layout"); checkIsAtGlobalLevel(typeSpecifier.line, "layout");
} }
if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut) if (sh::IsVarying(qualifier) || qualifier == EvqVertexIn || qualifier == EvqFragmentOut)
{ {
es3InputOutputTypeCheck(qualifier, typeSpecifier, typeSpecifier.line); checkInputOutputTypeIsValidES3(qualifier, typeSpecifier, typeSpecifier.line);
} }
if (qualifier == EvqComputeIn) if (qualifier == EvqComputeIn)
{ {
...@@ -1428,9 +1448,9 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, ...@@ -1428,9 +1448,9 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier,
return returnType; return returnType;
} }
void TParseContext::es3InputOutputTypeCheck(const TQualifier qualifier, void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
const TPublicType &type, const TPublicType &type,
const TSourceLoc &qualifierLocation) const TSourceLoc &qualifierLocation)
{ {
// An input/output variable can never be bool or a sampler. Samplers are checked elsewhere. // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
if (type.type == EbtBool) if (type.type == EbtBool)
...@@ -1525,7 +1545,7 @@ TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType, ...@@ -1525,7 +1545,7 @@ TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
{ {
singleDeclarationErrorCheck(publicType, identifierOrTypeLocation); singleDeclarationErrorCheck(publicType, identifierOrTypeLocation);
nonInitErrorCheck(identifierOrTypeLocation, identifier, &publicType); checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, &publicType);
TVariable *variable = nullptr; TVariable *variable = nullptr;
declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable); declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable);
...@@ -1547,17 +1567,16 @@ TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &public ...@@ -1547,17 +1567,16 @@ TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &public
singleDeclarationErrorCheck(publicType, identifierLocation); singleDeclarationErrorCheck(publicType, identifierLocation);
nonInitErrorCheck(identifierLocation, identifier, &publicType); checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
if (!arrayTypeErrorCheck(indexLocation, publicType)) if (!checkIsValidTypeForArray(indexLocation, publicType))
{ {
arrayQualifierErrorCheck(indexLocation, publicType); checkIsValidQualifierForArray(indexLocation, publicType);
} }
TType arrayType(publicType); TType arrayType(publicType);
int size; unsigned int size = checkIsValidArraySize(identifierLocation, indexExpression);
arraySizeErrorCheck(identifierLocation, indexExpression, size);
// Make the type an array even if size check failed. // Make the type an array even if size check failed.
// This ensures useless error messages regarding the variable's non-arrayness won't follow. // This ensures useless error messages regarding the variable's non-arrayness won't follow.
arrayType.setArraySize(size); arrayType.setArraySize(size);
...@@ -1609,19 +1628,19 @@ TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration( ...@@ -1609,19 +1628,19 @@ TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(
singleDeclarationErrorCheck(publicType, identifierLocation); singleDeclarationErrorCheck(publicType, identifierLocation);
if (!arrayTypeErrorCheck(indexLocation, publicType)) if (!checkIsValidTypeForArray(indexLocation, publicType))
{ {
arrayQualifierErrorCheck(indexLocation, publicType); checkIsValidQualifierForArray(indexLocation, publicType);
} }
TPublicType arrayType(publicType); TPublicType arrayType(publicType);
int size = 0; unsigned int size = 0u;
// If indexExpression is nullptr, then the array will eventually get its size implicitly from // If indexExpression is nullptr, then the array will eventually get its size implicitly from
// the initializer. // the initializer.
if (indexExpression != nullptr) if (indexExpression != nullptr)
{ {
arraySizeErrorCheck(identifierLocation, indexExpression, size); size = checkIsValidArraySize(identifierLocation, indexExpression);
} }
// Make the type an array even if size check failed. // Make the type an array even if size check failed.
// This ensures useless error messages regarding the variable's non-arrayness won't follow. // This ensures useless error messages regarding the variable's non-arrayness won't follow.
...@@ -1645,7 +1664,7 @@ TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &inv ...@@ -1645,7 +1664,7 @@ TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &inv
const TSymbol *symbol) const TSymbol *symbol)
{ {
// invariant declaration // invariant declaration
globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"); checkIsAtGlobalLevel(invariantLoc, "invariant varying");
if (!symbol) if (!symbol)
{ {
...@@ -1687,9 +1706,9 @@ TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType, ...@@ -1687,9 +1706,9 @@ TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType,
mDeferredSingleDeclarationErrorCheck = false; mDeferredSingleDeclarationErrorCheck = false;
} }
locationDeclaratorListCheck(identifierLocation, publicType); checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
nonInitErrorCheck(identifierLocation, identifier, &publicType); checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
TVariable *variable = nullptr; TVariable *variable = nullptr;
declareVariable(identifierLocation, identifier, TType(publicType), &variable); declareVariable(identifierLocation, identifier, TType(publicType), &variable);
...@@ -1717,16 +1736,15 @@ TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType, ...@@ -1717,16 +1736,15 @@ TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType,
mDeferredSingleDeclarationErrorCheck = false; mDeferredSingleDeclarationErrorCheck = false;
} }
locationDeclaratorListCheck(identifierLocation, publicType); checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
nonInitErrorCheck(identifierLocation, identifier, &publicType); checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, &publicType);
if (!arrayTypeErrorCheck(arrayLocation, publicType) && if (!checkIsValidTypeForArray(arrayLocation, publicType) &&
!arrayQualifierErrorCheck(arrayLocation, publicType)) !checkIsValidQualifierForArray(arrayLocation, publicType))
{ {
TType arrayType = TType(publicType); TType arrayType = TType(publicType);
int size; unsigned int size = checkIsValidArraySize(arrayLocation, indexExpression);
arraySizeErrorCheck(arrayLocation, indexExpression, size);
arrayType.setArraySize(size); arrayType.setArraySize(size);
TVariable *variable = nullptr; TVariable *variable = nullptr;
...@@ -1758,7 +1776,7 @@ TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicTy ...@@ -1758,7 +1776,7 @@ TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicTy
mDeferredSingleDeclarationErrorCheck = false; mDeferredSingleDeclarationErrorCheck = false;
} }
locationDeclaratorListCheck(identifierLocation, publicType); checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
TIntermNode *intermNode = nullptr; TIntermNode *intermNode = nullptr;
if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode)) if (!executeInitializer(identifierLocation, identifier, publicType, initializer, &intermNode))
...@@ -1798,21 +1816,21 @@ TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &pub ...@@ -1798,21 +1816,21 @@ TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &pub
mDeferredSingleDeclarationErrorCheck = false; mDeferredSingleDeclarationErrorCheck = false;
} }
locationDeclaratorListCheck(identifierLocation, publicType); checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
if (!arrayTypeErrorCheck(indexLocation, publicType)) if (!checkIsValidTypeForArray(indexLocation, publicType))
{ {
arrayQualifierErrorCheck(indexLocation, publicType); checkIsValidQualifierForArray(indexLocation, publicType);
} }
TPublicType arrayType(publicType); TPublicType arrayType(publicType);
int size = 0; unsigned int size = 0u;
// If indexExpression is nullptr, then the array will eventually get its size implicitly from // If indexExpression is nullptr, then the array will eventually get its size implicitly from
// the initializer. // the initializer.
if (indexExpression != nullptr) if (indexExpression != nullptr)
{ {
arraySizeErrorCheck(identifierLocation, indexExpression, size); size = checkIsValidArraySize(identifierLocation, indexExpression);
} }
// Make the type an array even if size check failed. // Make the type an array even if size check failed.
// This ensures useless error messages regarding the variable's non-arrayness won't follow. // This ensures useless error messages regarding the variable's non-arrayness won't follow.
...@@ -1908,7 +1926,7 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) ...@@ -1908,7 +1926,7 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
else else
{ {
if (layoutWorkGroupSizeErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier)) if (checkWorkGroupSizeIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier))
{ {
return; return;
} }
...@@ -1927,7 +1945,7 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) ...@@ -1927,7 +1945,7 @@ void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
return; return;
} }
layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier); checkLocationIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier);
if (layoutQualifier.matrixPacking != EmpUnspecified) if (layoutQualifier.matrixPacking != EmpUnspecified)
{ {
...@@ -2196,7 +2214,7 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type, ...@@ -2196,7 +2214,7 @@ TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
error(location, "no qualifiers allowed for function return", "layout"); error(location, "no qualifiers allowed for function return", "layout");
} }
// make sure a sampler is not involved as well... // make sure a sampler is not involved as well...
samplerErrorCheck(location, type, "samplers can't be function return values"); checkIsNotSampler(location, type, "samplers can't be function return values");
if (mShaderVersion < 300) if (mShaderVersion < 300)
{ {
// Array return values are forbidden, but there's also no valid syntax for declaring array // Array return values are forbidden, but there's also no valid syntax for declaring array
...@@ -2248,50 +2266,36 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn) ...@@ -2248,50 +2266,36 @@ TFunction *TParseContext::addConstructorFunc(const TPublicType &publicTypeIn)
// This function is used to test for the correctness of the parameters passed to various constructor // This function is used to test for the correctness of the parameters passed to various constructor
// functions and also convert them to the right datatype if it is allowed and required. // functions and also convert them to the right datatype if it is allowed and required.
// //
// Returns 0 for an error or the constructed node (aggregate or typed) for no error. // Returns a node to add to the tree regardless of if an error was generated or not.
// //
TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
TType *type,
TOperator op, TOperator op,
TFunction *fnCall, TFunction *fnCall,
const TSourceLoc &line) const TSourceLoc &line)
{ {
TIntermAggregate *constructor = arguments->getAsAggregate(); TType type = fnCall->getReturnType();
ASSERT(constructor != nullptr); if (type.isUnsizedArray())
if (type->isArray())
{ {
// GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of type.setArraySize(static_cast<unsigned int>(fnCall->getParamCount()));
// the array.
TIntermSequence *args = constructor->getSequence();
for (size_t i = 0; i < args->size(); i++)
{
const TType &argType = (*args)[i]->getAsTyped()->getType();
// It has already been checked that the argument is not an array.
ASSERT(!argType.isArray());
if (!argType.sameElementType(*type))
{
error(line, "Array constructor argument has an incorrect type", "Error");
return nullptr;
}
}
} }
else if (op == EOpConstructStruct) bool constType = true;
for (size_t i = 0; i < fnCall->getParamCount(); ++i)
{ {
const TFieldList &fields = type->getStruct()->fields(); const TConstParameter &param = fnCall->getParam(i);
TIntermSequence *args = constructor->getSequence(); if (param.type->getQualifier() != EvqConst)
constType = false;
for (size_t i = 0; i < fields.size(); i++) }
{ if (constType)
if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type()) type.setQualifier(EvqConst);
{
error(line, "Structure constructor arguments do not match structure fields",
"Error");
return 0; if (checkConstructorArguments(line, arguments, *fnCall, op, type))
} {
} TIntermTyped *dummyNode = intermediate.setAggregateOperator(nullptr, op, line);
dummyNode->setType(type);
return dummyNode;
} }
TIntermAggregate *constructor = arguments->getAsAggregate();
ASSERT(constructor != nullptr);
// Turn the argument list itself into a constructor // Turn the argument list itself into a constructor
constructor->setOp(op); constructor->setOp(op);
...@@ -2299,16 +2303,18 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, ...@@ -2299,16 +2303,18 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
ASSERT(constructor->isConstructor()); ASSERT(constructor->isConstructor());
// Need to set type before setPrecisionFromChildren() because bool doesn't have precision. // Need to set type before setPrecisionFromChildren() because bool doesn't have precision.
constructor->setType(*type); constructor->setType(type);
// Structs should not be precision qualified, the individual members may be. // Structs should not be precision qualified, the individual members may be.
// Built-in types on the other hand should be precision qualified. // Built-in types on the other hand should be precision qualified.
if (op != EOpConstructStruct) if (op != EOpConstructStruct)
{ {
constructor->setPrecisionFromChildren(); constructor->setPrecisionFromChildren();
type->setPrecision(constructor->getPrecision()); type.setPrecision(constructor->getPrecision());
} }
constructor->setType(type);
TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor); TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
if (constConstructor) if (constConstructor)
{ {
...@@ -2355,7 +2361,7 @@ TIntermConstantUnion *TParseContext::foldArraySubscript(int index, ...@@ -2355,7 +2361,7 @@ TIntermConstantUnion *TParseContext::foldArraySubscript(int index,
TIntermConstantUnion *baseNode, TIntermConstantUnion *baseNode,
const TSourceLoc &location) const TSourceLoc &location)
{ {
ASSERT(index < baseNode->getArraySize()); ASSERT(index < static_cast<int>(baseNode->getArraySize()));
TType arrayElementType = baseNode->getType(); TType arrayElementType = baseNode->getType();
arrayElementType.clearArrayness(); arrayElementType.clearArrayness();
...@@ -2422,7 +2428,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif ...@@ -2422,7 +2428,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
TIntermTyped *arrayIndex, TIntermTyped *arrayIndex,
const TSourceLoc &arrayIndexLine) const TSourceLoc &arrayIndexLine)
{ {
reservedErrorCheck(nameLine, blockName); checkIsNotReserved(nameLine, blockName);
if (typeQualifier.qualifier != EvqUniform) if (typeQualifier.qualifier != EvqUniform)
{ {
...@@ -2431,7 +2437,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif ...@@ -2431,7 +2437,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
} }
TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier); checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
if (blockLayoutQualifier.matrixPacking == EmpUnspecified) if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
{ {
...@@ -2443,7 +2449,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif ...@@ -2443,7 +2449,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
blockLayoutQualifier.blockStorage = mDefaultBlockStorage; blockLayoutQualifier.blockStorage = mDefaultBlockStorage;
} }
layoutWorkGroupSizeErrorCheck(nameLine, blockLayoutQualifier); checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName); TSymbol *blockNameSymbol = new TInterfaceBlockName(&blockName);
if (!symbolTable.declare(blockNameSymbol)) if (!symbolTable.declare(blockNameSymbol))
...@@ -2476,7 +2482,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif ...@@ -2476,7 +2482,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
// check layout qualifiers // check layout qualifiers
TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
layoutLocationErrorCheck(field->line(), fieldLayoutQualifier); checkLocationIsNotSpecified(field->line(), fieldLayoutQualifier);
if (fieldLayoutQualifier.blockStorage != EbsUnspecified) if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
{ {
...@@ -2499,10 +2505,10 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif ...@@ -2499,10 +2505,10 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
} }
// add array index // add array index
int arraySize = 0; unsigned int arraySize = 0;
if (arrayIndex != NULL) if (arrayIndex != nullptr)
{ {
arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize); arraySize = checkIsValidArraySize(arrayIndexLine, arrayIndex);
} }
TInterfaceBlock *interfaceBlock = TInterfaceBlock *interfaceBlock =
...@@ -2536,7 +2542,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif ...@@ -2536,7 +2542,7 @@ TIntermAggregate *TParseContext::addInterfaceBlock(const TPublicType &typeQualif
} }
else else
{ {
reservedErrorCheck(instanceLine, *instanceName); checkIsNotReserved(instanceLine, *instanceName);
// add a symbol for this interface block // add a symbol for this interface block
TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false); TVariable *instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
...@@ -3043,7 +3049,7 @@ void TParseContext::parseLocalSize(const TString &qualifierType, ...@@ -3043,7 +3049,7 @@ void TParseContext::parseLocalSize(const TString &qualifierType,
size_t index, size_t index,
TLocalSize *localSize) TLocalSize *localSize)
{ {
layoutSupportedErrorCheck(qualifierTypeLine, qualifierType, 310); checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
if (intValue < 1) if (intValue < 1)
{ {
std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive"; std::string errorMessage = std::string(getLocalSizeString(index)) + " must be positive";
...@@ -3194,9 +3200,9 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo ...@@ -3194,9 +3200,9 @@ TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpo
TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
TFieldList *fieldList) TFieldList *fieldList)
{ {
voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type); checkIsNonVoid(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type);
layoutWorkGroupSizeErrorCheck(typeSpecifier.line, typeSpecifier.layoutQualifier); checkWorkGroupSizeIsNotSpecified(typeSpecifier.line, typeSpecifier.layoutQualifier);
for (unsigned int i = 0; i < fieldList->size(); ++i) for (unsigned int i = 0; i < fieldList->size(); ++i)
{ {
...@@ -3214,10 +3220,10 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif ...@@ -3214,10 +3220,10 @@ TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecif
// don't allow arrays of arrays // don't allow arrays of arrays
if (type->isArray()) if (type->isArray())
{ {
arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier); checkIsValidTypeForArray(typeSpecifier.line, typeSpecifier);
} }
if (typeSpecifier.array) if (typeSpecifier.array)
type->setArraySize(typeSpecifier.arraySize); type->setArraySize(static_cast<unsigned int>(typeSpecifier.arraySize));
if (typeSpecifier.userDef) if (typeSpecifier.userDef)
{ {
type->setStruct(typeSpecifier.userDef->getStruct()); type->setStruct(typeSpecifier.userDef->getStruct());
...@@ -3244,7 +3250,7 @@ TPublicType TParseContext::addStructure(const TSourceLoc &structLine, ...@@ -3244,7 +3250,7 @@ TPublicType TParseContext::addStructure(const TSourceLoc &structLine,
if (!structName->empty()) if (!structName->empty())
{ {
reservedErrorCheck(nameLine, *structName); checkIsNotReserved(nameLine, *structName);
TVariable *userTypeDef = new TVariable(structName, *structureType, true); TVariable *userTypeDef = new TVariable(structName, *structureType, true);
if (!symbolTable.declare(userTypeDef)) if (!symbolTable.declare(userTypeDef))
{ {
...@@ -3418,7 +3424,7 @@ TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, ...@@ -3418,7 +3424,7 @@ TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
TIntermTyped *child, TIntermTyped *child,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
lValueErrorCheck(loc, GetOperatorString(op), child); checkCanBeLValue(loc, GetOperatorString(op), child);
return addUnaryMath(op, child, loc); return addUnaryMath(op, child, loc);
} }
...@@ -3827,25 +3833,8 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -3827,25 +3833,8 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
} }
else if (op != EOpNull) else if (op != EOpNull)
{ {
//
// Then this should be a constructor. // Then this should be a constructor.
// Don't go through the symbol table for constructors. callNode = addConstructor(paramNode, op, fnCall, loc);
// Their parameters will be verified algorithmically.
//
TType type(EbtVoid, EbpUndefined); // use this to get the type back
if (!constructorErrorCheck(loc, paramNode, *fnCall, op, &type))
{
//
// It's a constructor, of type 'type'.
//
callNode = addConstructor(paramNode, &type, op, fnCall, loc);
}
if (callNode == nullptr)
{
callNode = intermediate.setAggregateOperator(nullptr, op, loc);
}
callNode->setType(type);
} }
else else
{ {
...@@ -3862,7 +3851,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, ...@@ -3862,7 +3851,7 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// //
if (builtIn && !fnCandidate->getExtension().empty()) if (builtIn && !fnCandidate->getExtension().empty())
{ {
extensionErrorCheck(loc, fnCandidate->getExtension()); checkCanUseExtension(loc, fnCandidate->getExtension());
} }
op = fnCandidate->getBuiltInOp(); op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) if (builtIn && op != EOpNull)
...@@ -3967,7 +3956,7 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond, ...@@ -3967,7 +3956,7 @@ TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
TIntermTyped *falseBlock, TIntermTyped *falseBlock,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
boolErrorCheck(loc, cond); checkIsScalarBool(loc, cond);
if (trueBlock->getType() != falseBlock->getType()) if (trueBlock->getType() != falseBlock->getType())
{ {
......
...@@ -126,50 +126,55 @@ class TParseContext : angle::NonCopyable ...@@ -126,50 +126,55 @@ class TParseContext : angle::NonCopyable
bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line); bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc &line);
bool reservedErrorCheck(const TSourceLoc &line, const TString &identifier);
void assignError(const TSourceLoc &line, const char *op, TString left, TString right); void assignError(const TSourceLoc &line, const char *op, TString left, TString right);
void unaryOpError(const TSourceLoc &line, const char *op, TString operand); void unaryOpError(const TSourceLoc &line, const char *op, TString operand);
void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right); void binaryOpError(const TSourceLoc &line, const char *op, TString left, TString right);
void precisionErrorCheck(const TSourceLoc &line, TPrecision precision, TBasicType type);
bool lValueErrorCheck(const TSourceLoc &line, const char *op, TIntermTyped*); bool checkIsNotReserved(const TSourceLoc &line, const TString &identifier);
void constErrorCheck(TIntermTyped *node); void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type);
void integerErrorCheck(TIntermTyped *node, const char *token); bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node);
void globalErrorCheck(const TSourceLoc &line, bool global, const char *token); void checkIsConst(TIntermTyped *node);
bool constructorErrorCheck(const TSourceLoc &line, void checkIsScalarInteger(TIntermTyped *node, const char *token);
TIntermNode *argumentsNode, void checkIsAtGlobalLevel(const TSourceLoc &line, const char *token);
TFunction &function, bool checkConstructorArguments(const TSourceLoc &line,
TOperator op, TIntermNode *argumentsNode,
TType *type); const TFunction &function,
void arraySizeErrorCheck(const TSourceLoc &line, TIntermTyped *expr, int &size); TOperator op,
bool arrayQualifierErrorCheck(const TSourceLoc &line, const TPublicType &type); const TType &type);
bool arrayTypeErrorCheck(const TSourceLoc &line, const TPublicType &type);
bool voidErrorCheck(const TSourceLoc &line, const TString &identifier, const TBasicType &type); // Returns a sanitized array size to use (the size is at least 1).
void boolErrorCheck(const TSourceLoc &, const TIntermTyped *); unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr);
void boolErrorCheck(const TSourceLoc &, const TPublicType &); bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &type);
bool samplerErrorCheck(const TSourceLoc &line, const TPublicType &pType, const char *reason); bool checkIsValidTypeForArray(const TSourceLoc &line, const TPublicType &type);
void locationDeclaratorListCheck(const TSourceLoc &line, const TPublicType &pType); bool checkIsNonVoid(const TSourceLoc &line, const TString &identifier, const TBasicType &type);
void parameterSamplerErrorCheck(const TSourceLoc &line, void checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type);
TQualifier qualifier, void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType);
const TType &type); bool checkIsNotSampler(const TSourceLoc &line, const TPublicType &pType, const char *reason);
void paramErrorCheck(const TSourceLoc &line, void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType);
TQualifier qualifier, void checkLocationIsNotSpecified(const TSourceLoc &location,
TQualifier paramQualifier, const TLayoutQualifier &layoutQualifier);
TType *type); void checkOutParameterIsNotSampler(const TSourceLoc &line,
bool extensionErrorCheck(const TSourceLoc &line, const TString&); TQualifier qualifier,
const TType &type);
void checkIsParameterQualifierValid(const TSourceLoc &line,
TQualifier qualifier,
TQualifier paramQualifier,
TType *type);
bool checkCanUseExtension(const TSourceLoc &line, const TString &extension);
void singleDeclarationErrorCheck(const TPublicType &publicType, void singleDeclarationErrorCheck(const TPublicType &publicType,
const TSourceLoc &identifierLocation); const TSourceLoc &identifierLocation);
void layoutLocationErrorCheck(const TSourceLoc &location, void checkLayoutQualifierSupported(const TSourceLoc &location,
const TLayoutQualifier &layoutQualifier); const TString &layoutQualifierName,
void layoutSupportedErrorCheck(const TSourceLoc &location, int versionRequired);
const TString &layoutQualifierName, bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
int versionRequired); const TLayoutQualifier &layoutQualifier);
bool layoutWorkGroupSizeErrorCheck(const TSourceLoc &location,
const TLayoutQualifier &layoutQualifier); void functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
void functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *); void checkInvariantIsOutVariableES3(const TQualifier qualifier,
void es3InvariantErrorCheck(const TQualifier qualifier, const TSourceLoc &invariantLocation); const TSourceLoc &invariantLocation);
void es3InputOutputTypeCheck(const TQualifier qualifier, void checkInputOutputTypeIsValidES3(const TQualifier qualifier,
const TPublicType &type, const TPublicType &type,
const TSourceLoc &qualifierLocation); const TSourceLoc &qualifierLocation);
const TPragma &pragma() const { return mDirectiveHandler.pragma(); } const TPragma &pragma() const { return mDirectiveHandler.pragma(); }
const TExtensionBehavior &extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); } const TExtensionBehavior &extensionBehavior() const { return mDirectiveHandler.extensionBehavior(); }
...@@ -265,7 +270,6 @@ class TParseContext : angle::NonCopyable ...@@ -265,7 +270,6 @@ class TParseContext : angle::NonCopyable
const TSourceLoc &location); const TSourceLoc &location);
TFunction *addConstructorFunc(const TPublicType &publicType); TFunction *addConstructorFunc(const TPublicType &publicType);
TIntermTyped *addConstructor(TIntermNode *arguments, TIntermTyped *addConstructor(TIntermNode *arguments,
TType *type,
TOperator op, TOperator op,
TFunction *fnCall, TFunction *fnCall,
const TSourceLoc &line); const TSourceLoc &line);
...@@ -375,7 +379,9 @@ class TParseContext : angle::NonCopyable ...@@ -375,7 +379,9 @@ class TParseContext : angle::NonCopyable
bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable); bool declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type, TVariable **variable);
void nonInitErrorCheck(const TSourceLoc &line, const TString &identifier, TPublicType *type); void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
const TString &identifier,
TPublicType *type);
TIntermTyped *addBinaryMathInternal( TIntermTyped *addBinaryMathInternal(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
......
...@@ -318,7 +318,6 @@ size_t TType::getObjectSize() const ...@@ -318,7 +318,6 @@ size_t TType::getObjectSize() const
if (isArray()) if (isArray())
{ {
// TODO: getArraySize() returns an int, not a size_t
size_t currentArraySize = getArraySize(); size_t currentArraySize = getArraySize();
if (currentArraySize > INT_MAX / totalSize) if (currentArraySize > INT_MAX / totalSize)
totalSize = INT_MAX; totalSize = INT_MAX;
...@@ -364,7 +363,7 @@ bool TStructure::containsSamplers() const ...@@ -364,7 +363,7 @@ bool TStructure::containsSamplers() const
void TStructure::createSamplerSymbols(const TString &structName, void TStructure::createSamplerSymbols(const TString &structName,
const TString &structAPIName, const TString &structAPIName,
const int arrayOfStructsSize, const unsigned int arrayOfStructsSize,
TVector<TIntermSymbol *> *outputSymbols, TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
{ {
...@@ -373,9 +372,9 @@ void TStructure::createSamplerSymbols(const TString &structName, ...@@ -373,9 +372,9 @@ void TStructure::createSamplerSymbols(const TString &structName,
const TType *fieldType = field->type(); const TType *fieldType = field->type();
if (IsSampler(fieldType->getBasicType())) if (IsSampler(fieldType->getBasicType()))
{ {
if (arrayOfStructsSize > 0) if (arrayOfStructsSize > 0u)
{ {
for (int arrayIndex = 0; arrayIndex < arrayOfStructsSize; ++arrayIndex) for (unsigned int arrayIndex = 0u; arrayIndex < arrayOfStructsSize; ++arrayIndex)
{ {
TStringStream name; TStringStream name;
name << structName << "_" << arrayIndex << "_" << field->name(); name << structName << "_" << arrayIndex << "_" << field->name();
...@@ -405,10 +404,11 @@ void TStructure::createSamplerSymbols(const TString &structName, ...@@ -405,10 +404,11 @@ void TStructure::createSamplerSymbols(const TString &structName,
} }
else if (fieldType->isStructureContainingSamplers()) else if (fieldType->isStructureContainingSamplers())
{ {
int nestedArrayOfStructsSize = fieldType->isArray() ? fieldType->getArraySize() : 0; unsigned int nestedArrayOfStructsSize =
fieldType->isArray() ? fieldType->getArraySize() : 0u;
if (arrayOfStructsSize > 0) if (arrayOfStructsSize > 0)
{ {
for (int arrayIndex = 0; arrayIndex < arrayOfStructsSize; ++arrayIndex) for (unsigned int arrayIndex = 0u; arrayIndex < arrayOfStructsSize; ++arrayIndex)
{ {
TStringStream fieldName; TStringStream fieldName;
fieldName << structName << "_" << arrayIndex << "_" << field->name(); fieldName << structName << "_" << arrayIndex << "_" << field->name();
......
...@@ -123,7 +123,7 @@ class TStructure : public TFieldListCollection ...@@ -123,7 +123,7 @@ class TStructure : public TFieldListCollection
void createSamplerSymbols(const TString &structName, void createSamplerSymbols(const TString &structName,
const TString &structAPIName, const TString &structAPIName,
const int arrayOfStructsSize, const unsigned int arrayOfStructsSize,
TVector<TIntermSymbol *> *outputSymbols, TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const; TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const;
...@@ -387,13 +387,10 @@ class TType ...@@ -387,13 +387,10 @@ class TType
} }
bool isUnsizedArray() const bool isUnsizedArray() const
{ {
return array && arraySize == 0; return array && arraySize == 0u;
} }
int getArraySize() const unsigned int getArraySize() const { return arraySize; }
{ void setArraySize(unsigned int s)
return arraySize;
}
void setArraySize(int s)
{ {
if (!array || arraySize != s) if (!array || arraySize != s)
{ {
...@@ -407,7 +404,7 @@ class TType ...@@ -407,7 +404,7 @@ class TType
if (array) if (array)
{ {
array = false; array = false;
arraySize = 0; arraySize = 0u;
invalidateMangledName(); invalidateMangledName();
} }
} }
...@@ -556,7 +553,7 @@ class TType ...@@ -556,7 +553,7 @@ class TType
void createSamplerSymbols(const TString &structName, void createSamplerSymbols(const TString &structName,
const TString &structAPIName, const TString &structAPIName,
const int arrayOfStructsSize, const unsigned int arrayOfStructsSize,
TVector<TIntermSymbol *> *outputSymbols, TVector<TIntermSymbol *> *outputSymbols,
TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const TMap<TIntermSymbol *, TString> *outputSymbolsToAPINames) const
{ {
...@@ -584,7 +581,7 @@ class TType ...@@ -584,7 +581,7 @@ class TType
unsigned char primarySize; // size of vector or cols matrix unsigned char primarySize; // size of vector or cols matrix
unsigned char secondarySize; // rows of a matrix unsigned char secondarySize; // rows of a matrix
bool array; bool array;
int arraySize; unsigned int arraySize;
// 0 unless this is an interface block, or interface block member variable // 0 unless this is an interface block, or interface block member variable
TInterfaceBlock *interfaceBlock; TInterfaceBlock *interfaceBlock;
......
...@@ -128,7 +128,7 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type ...@@ -128,7 +128,7 @@ unsigned int UniformHLSL::assignSamplerInStructUniformRegister(const TType &type
ASSERT(IsSampler(type.getBasicType())); ASSERT(IsSampler(type.getBasicType()));
unsigned int registerIndex = mSamplerRegister; unsigned int registerIndex = mSamplerRegister;
mUniformRegisterMap[std::string(name.c_str())] = registerIndex; mUniformRegisterMap[std::string(name.c_str())] = registerIndex;
unsigned int registerCount = type.isArray() ? type.getArraySize() : 1; unsigned int registerCount = type.isArray() ? type.getArraySize() : 1u;
mSamplerRegister += registerCount; mSamplerRegister += registerCount;
if (outRegisterCount) if (outRegisterCount)
{ {
...@@ -175,9 +175,9 @@ void UniformHLSL::outputHLSLSamplerUniformGroup( ...@@ -175,9 +175,9 @@ void UniformHLSL::outputHLSLSamplerUniformGroup(
{ {
out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type) out << "static const uint " << DecorateIfNeeded(uniform->getName()) << ArrayString(type)
<< " = {"; << " = {";
for (int i = 0; i < type.getArraySize(); ++i) for (unsigned int i = 0u; i < type.getArraySize(); ++i)
{ {
if (i > 0) if (i > 0u)
out << ", "; out << ", ";
out << (samplerArrayIndex + i); out << (samplerArrayIndex + i);
} }
...@@ -281,7 +281,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out, ...@@ -281,7 +281,7 @@ void UniformHLSL::uniformsHeader(TInfoSinkBase &out,
{ {
TVector<TIntermSymbol *> samplerSymbols; TVector<TIntermSymbol *> samplerSymbols;
TMap<TIntermSymbol *, TString> symbolsToAPINames; TMap<TIntermSymbol *, TString> symbolsToAPINames;
int arrayOfStructsSize = type.isArray() ? type.getArraySize() : 0; unsigned int arrayOfStructsSize = type.isArray() ? type.getArraySize() : 0u;
type.createSamplerSymbols("angle_" + name.getString(), name.getString(), type.createSamplerSymbols("angle_" + name.getString(), name.getString(),
arrayOfStructsSize, &samplerSymbols, &symbolsToAPINames); arrayOfStructsSize, &samplerSymbols, &symbolsToAPINames);
for (TIntermSymbol *sampler : samplerSymbols) for (TIntermSymbol *sampler : samplerSymbols)
......
...@@ -60,7 +60,7 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const ...@@ -60,7 +60,7 @@ int ValidateOutputs::validateAndCountErrors(TInfoSinkBase &sink) const
for (const auto &symbol : mOutputs) for (const auto &symbol : mOutputs)
{ {
const TType &type = symbol->getType(); const TType &type = symbol->getType();
const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1); const size_t elementCount = static_cast<size_t>(type.isArray() ? type.getArraySize() : 1u);
const size_t location = static_cast<size_t>(type.getLayoutQualifier().location); const size_t location = static_cast<size_t>(type.getLayoutQualifier().location);
ASSERT(type.getLayoutQualifier().location != -1); ASSERT(type.getLayoutQualifier().location != -1);
......
...@@ -477,7 +477,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, ...@@ -477,7 +477,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
attribute.type = GLVariableType(type); attribute.type = GLVariableType(type);
attribute.precision = GLVariablePrecision(type); attribute.precision = GLVariablePrecision(type);
attribute.name = variable->getSymbol().c_str(); attribute.name = variable->getSymbol().c_str();
attribute.arraySize = static_cast<unsigned int>(type.getArraySize()); attribute.arraySize = type.getArraySize();
attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
attribute.location = variable->getType().getLayoutQualifier().location; attribute.location = variable->getType().getLayoutQualifier().location;
...@@ -497,7 +497,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, ...@@ -497,7 +497,7 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable,
attribute.type = GLVariableType(type); attribute.type = GLVariableType(type);
attribute.precision = GLVariablePrecision(type); attribute.precision = GLVariablePrecision(type);
attribute.name = variable->getSymbol().c_str(); attribute.name = variable->getSymbol().c_str();
attribute.arraySize = static_cast<unsigned int>(type.getArraySize()); attribute.arraySize = type.getArraySize();
attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
attribute.location = variable->getType().getLayoutQualifier().location; attribute.location = variable->getType().getLayoutQualifier().location;
......
...@@ -290,7 +290,7 @@ postfix_expression ...@@ -290,7 +290,7 @@ postfix_expression
integer_expression integer_expression
: expression { : expression {
context->integerErrorCheck($1, "[]"); context->checkIsScalarInteger($1, "[]");
$$ = $1; $$ = $1;
} }
; ;
...@@ -369,13 +369,13 @@ function_identifier ...@@ -369,13 +369,13 @@ function_identifier
$$ = context->addConstructorFunc($1); $$ = context->addConstructorFunc($1);
} }
| IDENTIFIER { | IDENTIFIER {
context->reservedErrorCheck(@1, *$1.string); context->checkIsNotReserved(@1, *$1.string);
const TType *type = TCache::getType(EbtVoid, EbpUndefined); const TType *type = TCache::getType(EbtVoid, EbpUndefined);
TFunction *function = new TFunction($1.string, type); TFunction *function = new TFunction($1.string, type);
$$ = function; $$ = function;
} }
| FIELD_SELECTION { | FIELD_SELECTION {
context->reservedErrorCheck(@1, *$1.string); context->checkIsNotReserved(@1, *$1.string);
const TType *type = TCache::getType(EbtVoid, EbpUndefined); const TType *type = TCache::getType(EbtVoid, EbpUndefined);
TFunction *function = new TFunction($1.string, type); TFunction *function = new TFunction($1.string, type);
$$ = function; $$ = function;
...@@ -529,7 +529,7 @@ conditional_expression ...@@ -529,7 +529,7 @@ conditional_expression
assignment_expression assignment_expression
: conditional_expression { $$ = $1; } : conditional_expression { $$ = $1; }
| unary_expression assignment_operator assignment_expression { | unary_expression assignment_operator assignment_expression {
context->lValueErrorCheck(@2, "assign", $1); context->checkCanBeLValue(@2, "assign", $1);
$$ = context->addAssign($2.op, $1, $3, @2); $$ = context->addAssign($2.op, $1, $3, @2);
} }
; ;
...@@ -577,7 +577,7 @@ expression ...@@ -577,7 +577,7 @@ expression
constant_expression constant_expression
: conditional_expression { : conditional_expression {
context->constErrorCheck($1); context->checkIsConst($1);
$$ = $1; $$ = $1;
} }
; ;
...@@ -684,18 +684,17 @@ parameter_declarator ...@@ -684,18 +684,17 @@ parameter_declarator
if ($1.type == EbtVoid) { if ($1.type == EbtVoid) {
context->error(@2, "illegal use of type 'void'", $2.string->c_str()); context->error(@2, "illegal use of type 'void'", $2.string->c_str());
} }
context->reservedErrorCheck(@2, *$2.string); context->checkIsNotReserved(@2, *$2.string);
TParameter param = {$2.string, new TType($1)}; TParameter param = {$2.string, new TType($1)};
$$.param = param; $$.param = param;
} }
| type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { | type_specifier identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
// Check that we can make an array out of this type // Check that we can make an array out of this type
context->arrayTypeErrorCheck(@3, $1); context->checkIsValidTypeForArray(@3, $1);
context->reservedErrorCheck(@2, *$2.string); context->checkIsNotReserved(@2, *$2.string);
int size; unsigned int size = context->checkIsValidArraySize(@3, $4);
context->arraySizeErrorCheck(@3, $4, size);
$1.setArraySize(size); $1.setArraySize(size);
...@@ -716,24 +715,24 @@ parameter_declaration ...@@ -716,24 +715,24 @@ parameter_declaration
// //
: parameter_type_qualifier parameter_qualifier parameter_declarator { : parameter_type_qualifier parameter_qualifier parameter_declarator {
$$ = $3; $$ = $3;
context->paramErrorCheck(@3, $1, $2, $$.param.type); context->checkIsParameterQualifierValid(@3, $1, $2, $$.param.type);
} }
| parameter_qualifier parameter_declarator { | parameter_qualifier parameter_declarator {
$$ = $2; $$ = $2;
context->parameterSamplerErrorCheck(@2, $1, *$2.param.type); context->checkOutParameterIsNotSampler(@2, $1, *$2.param.type);
context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type); context->checkIsParameterQualifierValid(@2, EvqTemporary, $1, $$.param.type);
} }
// //
// Only type // Only type
// //
| parameter_type_qualifier parameter_qualifier parameter_type_specifier { | parameter_type_qualifier parameter_qualifier parameter_type_specifier {
$$ = $3; $$ = $3;
context->paramErrorCheck(@3, $1, $2, $$.param.type); context->checkIsParameterQualifierValid(@3, $1, $2, $$.param.type);
} }
| parameter_qualifier parameter_type_specifier { | parameter_qualifier parameter_type_specifier {
$$ = $2; $$ = $2;
context->parameterSamplerErrorCheck(@2, $1, *$2.param.type); context->checkOutParameterIsNotSampler(@2, $1, *$2.param.type);
context->paramErrorCheck(@2, EvqTemporary, $1, $$.param.type); context->checkIsParameterQualifierValid(@2, EvqTemporary, $1, $$.param.type);
} }
; ;
...@@ -855,12 +854,12 @@ type_qualifier ...@@ -855,12 +854,12 @@ type_qualifier
: ATTRIBUTE { : ATTRIBUTE {
VERTEX_ONLY("attribute", @1); VERTEX_ONLY("attribute", @1);
ES2_ONLY("attribute", @1); ES2_ONLY("attribute", @1);
context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute"); context->checkIsAtGlobalLevel(@1, "attribute");
$$.setBasic(EbtVoid, EvqAttribute, @1); $$.setBasic(EbtVoid, EvqAttribute, @1);
} }
| VARYING { | VARYING {
ES2_ONLY("varying", @1); ES2_ONLY("varying", @1);
context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying"); context->checkIsAtGlobalLevel(@1, "varying");
if (context->getShaderType() == GL_VERTEX_SHADER) if (context->getShaderType() == GL_VERTEX_SHADER)
$$.setBasic(EbtVoid, EvqVaryingOut, @1); $$.setBasic(EbtVoid, EvqVaryingOut, @1);
else else
...@@ -868,7 +867,7 @@ type_qualifier ...@@ -868,7 +867,7 @@ type_qualifier
} }
| INVARIANT VARYING { | INVARIANT VARYING {
ES2_ONLY("varying", @1); ES2_ONLY("varying", @1);
context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying"); context->checkIsAtGlobalLevel(@1, "invariant varying");
if (context->getShaderType() == GL_VERTEX_SHADER) if (context->getShaderType() == GL_VERTEX_SHADER)
$$.setBasic(EbtVoid, EvqVaryingOut, @1); $$.setBasic(EbtVoid, EvqVaryingOut, @1);
else else
...@@ -900,12 +899,12 @@ type_qualifier ...@@ -900,12 +899,12 @@ type_qualifier
$$.layoutQualifier = $1; $$.layoutQualifier = $1;
} }
| INVARIANT storage_qualifier { | INVARIANT storage_qualifier {
context->es3InvariantErrorCheck($2.qualifier, @1); context->checkInvariantIsOutVariableES3($2.qualifier, @1);
$$.setBasic(EbtVoid, $2.qualifier, @2); $$.setBasic(EbtVoid, $2.qualifier, @2);
$$.invariant = true; $$.invariant = true;
} }
| INVARIANT interpolation_qualifier storage_qualifier { | INVARIANT interpolation_qualifier storage_qualifier {
context->es3InvariantErrorCheck($3.qualifier, @1); context->checkInvariantIsOutVariableES3($3.qualifier, @1);
$$ = context->joinInterpolationQualifiers(@2, $2.qualifier, @3, $3.qualifier); $$ = context->joinInterpolationQualifiers(@2, $2.qualifier, @3, $3.qualifier);
$$.invariant = true; $$.invariant = true;
} }
...@@ -947,7 +946,7 @@ storage_qualifier ...@@ -947,7 +946,7 @@ storage_qualifier
$$.qualifier = EvqCentroidOut; $$.qualifier = EvqCentroidOut;
} }
| UNIFORM { | UNIFORM {
context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform"); context->checkIsAtGlobalLevel(@1, "uniform");
$$.qualifier = EvqUniform; $$.qualifier = EvqUniform;
} }
; ;
...@@ -958,7 +957,7 @@ type_specifier ...@@ -958,7 +957,7 @@ type_specifier
if ($$.precision == EbpUndefined) { if ($$.precision == EbpUndefined) {
$$.precision = context->symbolTable.getDefaultPrecision($1.type); $$.precision = context->symbolTable.getDefaultPrecision($1.type);
context->precisionErrorCheck(@1, $$.precision, $1.type); context->checkPrecisionSpecified(@1, $$.precision, $1.type);
} }
} }
| precision_qualifier type_specifier_no_prec { | precision_qualifier type_specifier_no_prec {
...@@ -1023,10 +1022,9 @@ type_specifier_no_prec ...@@ -1023,10 +1022,9 @@ type_specifier_no_prec
| type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET { | type_specifier_nonarray LEFT_BRACKET constant_expression RIGHT_BRACKET {
$$ = $1; $$ = $1;
if (!context->arrayTypeErrorCheck(@2, $1)) if (!context->checkIsValidTypeForArray(@2, $1))
{ {
int size; unsigned int size = context->checkIsValidArraySize(@2, $3);
context->arraySizeErrorCheck(@2, $3, size);
$$.setArraySize(size); $$.setArraySize(size);
} }
} }
...@@ -1300,17 +1298,16 @@ struct_declarator_list ...@@ -1300,17 +1298,16 @@ struct_declarator_list
struct_declarator struct_declarator
: identifier { : identifier {
context->reservedErrorCheck(@1, *$1.string); context->checkIsNotReserved(@1, *$1.string);
TType* type = new TType(EbtVoid, EbpUndefined); TType* type = new TType(EbtVoid, EbpUndefined);
$$ = new TField(type, $1.string, @1); $$ = new TField(type, $1.string, @1);
} }
| identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
context->reservedErrorCheck(@1, *$1.string); context->checkIsNotReserved(@1, *$1.string);
TType* type = new TType(EbtVoid, EbpUndefined); TType* type = new TType(EbtVoid, EbpUndefined);
int size; unsigned int size = context->checkIsValidArraySize(@3, $3);
context->arraySizeErrorCheck(@3, $3, size);
type->setArraySize(size); type->setArraySize(size);
$$ = new TField(type, $1.string, @1); $$ = new TField(type, $1.string, @1);
...@@ -1393,7 +1390,7 @@ expression_statement ...@@ -1393,7 +1390,7 @@ expression_statement
selection_statement selection_statement
: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement {
context->boolErrorCheck(@1, $3); context->checkIsScalarBool(@1, $3);
$$ = context->intermediate.addSelection($3, $5, @1); $$ = context->intermediate.addSelection($3, $5, @1);
} }
; ;
...@@ -1429,11 +1426,11 @@ condition ...@@ -1429,11 +1426,11 @@ condition
// In 1996 c++ draft, conditions can include single declarations // In 1996 c++ draft, conditions can include single declarations
: expression { : expression {
$$ = $1; $$ = $1;
context->boolErrorCheck($1->getLine(), $1); context->checkIsScalarBool($1->getLine(), $1);
} }
| fully_specified_type identifier EQUAL initializer { | fully_specified_type identifier EQUAL initializer {
TIntermNode *intermNode; TIntermNode *intermNode;
context->boolErrorCheck(@2, $1); context->checkIsScalarBool(@2, $1);
if (!context->executeInitializer(@2, *$2.string, $1, $4, &intermNode)) if (!context->executeInitializer(@2, *$2.string, $1, $4, &intermNode))
$$ = $4; $$ = $4;
...@@ -1450,7 +1447,7 @@ iteration_statement ...@@ -1450,7 +1447,7 @@ iteration_statement
context->decrLoopNestingLevel(); context->decrLoopNestingLevel();
} }
| DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { | DO { context->incrLoopNestingLevel(); } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
context->boolErrorCheck(@8, $6); context->checkIsScalarBool(@8, $6);
$$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4); $$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
context->decrLoopNestingLevel(); context->decrLoopNestingLevel();
......
...@@ -720,24 +720,24 @@ static const yytype_uint16 yyrline[] = ...@@ -720,24 +720,24 @@ static const yytype_uint16 yyrline[] =
524, 530, 531, 538, 539, 540, 541, 545, 546, 547, 524, 530, 531, 538, 539, 540, 541, 545, 546, 547,
551, 555, 559, 563, 570, 573, 579, 586, 593, 596, 551, 555, 559, 563, 570, 573, 579, 586, 593, 596,
602, 611, 615, 619, 623, 630, 636, 639, 646, 654, 602, 611, 615, 619, 623, 630, 636, 639, 646, 654,
674, 683, 691, 717, 721, 729, 733, 741, 744, 747, 674, 683, 691, 716, 720, 728, 732, 740, 743, 746,
750, 756, 763, 766, 770, 774, 779, 784, 791, 795, 749, 755, 762, 765, 769, 773, 778, 783, 790, 794,
799, 803, 808, 813, 817, 824, 834, 840, 843, 849, 798, 802, 807, 812, 816, 823, 833, 839, 842, 848,
855, 861, 869, 878, 885, 888, 894, 898, 902, 907, 854, 860, 868, 877, 884, 887, 893, 897, 901, 906,
915, 918, 934, 939, 944, 949, 956, 964, 975, 978, 914, 917, 933, 938, 943, 948, 955, 963, 974, 977,
981, 987, 994, 997, 1003, 1006, 1009, 1015, 1018, 1023, 980, 986, 993, 996, 1002, 1005, 1008, 1014, 1017, 1022,
1036, 1040, 1044, 1048, 1052, 1056, 1061, 1066, 1071, 1076, 1034, 1038, 1042, 1046, 1050, 1054, 1059, 1064, 1069, 1074,
1081, 1086, 1091, 1096, 1101, 1106, 1111, 1116, 1121, 1126, 1079, 1084, 1089, 1094, 1099, 1104, 1109, 1114, 1119, 1124,
1131, 1136, 1141, 1146, 1151, 1156, 1161, 1165, 1169, 1173, 1129, 1134, 1139, 1144, 1149, 1154, 1159, 1163, 1167, 1171,
1177, 1181, 1185, 1189, 1193, 1197, 1201, 1205, 1209, 1213, 1175, 1179, 1183, 1187, 1191, 1195, 1199, 1203, 1207, 1211,
1217, 1221, 1229, 1236, 1240, 1253, 1253, 1256, 1256, 1262, 1215, 1219, 1227, 1234, 1238, 1251, 1251, 1254, 1254, 1260,
1265, 1280, 1283, 1292, 1296, 1302, 1308, 1321, 1325, 1329, 1263, 1278, 1281, 1290, 1294, 1300, 1306, 1318, 1322, 1326,
1330, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1346, 1347, 1327, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1343, 1344,
1347, 1347, 1357, 1358, 1362, 1362, 1363, 1363, 1368, 1371, 1344, 1344, 1354, 1355, 1359, 1359, 1360, 1360, 1365, 1368,
1381, 1384, 1390, 1391, 1395, 1402, 1406, 1413, 1413, 1420, 1378, 1381, 1387, 1388, 1392, 1399, 1403, 1410, 1410, 1417,
1423, 1430, 1434, 1447, 1447, 1452, 1452, 1458, 1458, 1466, 1420, 1427, 1431, 1444, 1444, 1449, 1449, 1455, 1455, 1463,
1469, 1475, 1478, 1484, 1488, 1495, 1498, 1501, 1504, 1507, 1466, 1472, 1475, 1481, 1485, 1492, 1495, 1498, 1501, 1504,
1516, 1520, 1527, 1530, 1536, 1536 1513, 1517, 1524, 1527, 1533, 1533
}; };
#endif #endif
...@@ -2487,7 +2487,7 @@ yyreduce: ...@@ -2487,7 +2487,7 @@ yyreduce:
case 17: case 17:
{ {
context->integerErrorCheck((yyvsp[0].interm.intermTypedNode), "[]"); context->checkIsScalarInteger((yyvsp[0].interm.intermTypedNode), "[]");
(yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
} }
...@@ -2603,7 +2603,7 @@ yyreduce: ...@@ -2603,7 +2603,7 @@ yyreduce:
case 29: case 29:
{ {
context->reservedErrorCheck((yylsp[0]), *(yyvsp[0].lex).string); context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
const TType *type = TCache::getType(EbtVoid, EbpUndefined); const TType *type = TCache::getType(EbtVoid, EbpUndefined);
TFunction *function = new TFunction((yyvsp[0].lex).string, type); TFunction *function = new TFunction((yyvsp[0].lex).string, type);
(yyval.interm.function) = function; (yyval.interm.function) = function;
...@@ -2614,7 +2614,7 @@ yyreduce: ...@@ -2614,7 +2614,7 @@ yyreduce:
case 30: case 30:
{ {
context->reservedErrorCheck((yylsp[0]), *(yyvsp[0].lex).string); context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
const TType *type = TCache::getType(EbtVoid, EbpUndefined); const TType *type = TCache::getType(EbtVoid, EbpUndefined);
TFunction *function = new TFunction((yyvsp[0].lex).string, type); TFunction *function = new TFunction((yyvsp[0].lex).string, type);
(yyval.interm.function) = function; (yyval.interm.function) = function;
...@@ -2931,7 +2931,7 @@ yyreduce: ...@@ -2931,7 +2931,7 @@ yyreduce:
case 72: case 72:
{ {
context->lValueErrorCheck((yylsp[-1]), "assign", (yyvsp[-2].interm.intermTypedNode)); context->checkCanBeLValue((yylsp[-1]), "assign", (yyvsp[-2].interm.intermTypedNode));
(yyval.interm.intermTypedNode) = context->addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1])); (yyval.interm.intermTypedNode) = context->addAssign((yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yylsp[-1]));
} }
...@@ -3040,7 +3040,7 @@ yyreduce: ...@@ -3040,7 +3040,7 @@ yyreduce:
case 86: case 86:
{ {
context->constErrorCheck((yyvsp[0].interm.intermTypedNode)); context->checkIsConst((yyvsp[0].interm.intermTypedNode));
(yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
} }
...@@ -3199,7 +3199,7 @@ yyreduce: ...@@ -3199,7 +3199,7 @@ yyreduce:
if ((yyvsp[-1].interm.type).type == EbtVoid) { if ((yyvsp[-1].interm.type).type == EbtVoid) {
context->error((yylsp[0]), "illegal use of type 'void'", (yyvsp[0].lex).string->c_str()); context->error((yylsp[0]), "illegal use of type 'void'", (yyvsp[0].lex).string->c_str());
} }
context->reservedErrorCheck((yylsp[0]), *(yyvsp[0].lex).string); context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))}; TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))};
(yyval.interm).param = param; (yyval.interm).param = param;
} }
...@@ -3210,12 +3210,11 @@ yyreduce: ...@@ -3210,12 +3210,11 @@ yyreduce:
{ {
// Check that we can make an array out of this type // Check that we can make an array out of this type
context->arrayTypeErrorCheck((yylsp[-2]), (yyvsp[-4].interm.type)); context->checkIsValidTypeForArray((yylsp[-2]), (yyvsp[-4].interm.type));
context->reservedErrorCheck((yylsp[-3]), *(yyvsp[-3].lex).string); context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string);
int size; unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
context->arraySizeErrorCheck((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode), size);
(yyvsp[-4].interm.type).setArraySize(size); (yyvsp[-4].interm.type).setArraySize(size);
...@@ -3230,7 +3229,7 @@ yyreduce: ...@@ -3230,7 +3229,7 @@ yyreduce:
{ {
(yyval.interm) = (yyvsp[0].interm); (yyval.interm) = (yyvsp[0].interm);
context->paramErrorCheck((yylsp[0]), (yyvsp[-2].interm.qualifier), (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); context->checkIsParameterQualifierValid((yylsp[0]), (yyvsp[-2].interm.qualifier), (yyvsp[-1].interm.qualifier), (yyval.interm).param.type);
} }
break; break;
...@@ -3239,8 +3238,8 @@ yyreduce: ...@@ -3239,8 +3238,8 @@ yyreduce:
{ {
(yyval.interm) = (yyvsp[0].interm); (yyval.interm) = (yyvsp[0].interm);
context->parameterSamplerErrorCheck((yylsp[0]), (yyvsp[-1].interm.qualifier), *(yyvsp[0].interm).param.type); context->checkOutParameterIsNotSampler((yylsp[0]), (yyvsp[-1].interm.qualifier), *(yyvsp[0].interm).param.type);
context->paramErrorCheck((yylsp[0]), EvqTemporary, (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); context->checkIsParameterQualifierValid((yylsp[0]), EvqTemporary, (yyvsp[-1].interm.qualifier), (yyval.interm).param.type);
} }
break; break;
...@@ -3249,7 +3248,7 @@ yyreduce: ...@@ -3249,7 +3248,7 @@ yyreduce:
{ {
(yyval.interm) = (yyvsp[0].interm); (yyval.interm) = (yyvsp[0].interm);
context->paramErrorCheck((yylsp[0]), (yyvsp[-2].interm.qualifier), (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); context->checkIsParameterQualifierValid((yylsp[0]), (yyvsp[-2].interm.qualifier), (yyvsp[-1].interm.qualifier), (yyval.interm).param.type);
} }
break; break;
...@@ -3258,8 +3257,8 @@ yyreduce: ...@@ -3258,8 +3257,8 @@ yyreduce:
{ {
(yyval.interm) = (yyvsp[0].interm); (yyval.interm) = (yyvsp[0].interm);
context->parameterSamplerErrorCheck((yylsp[0]), (yyvsp[-1].interm.qualifier), *(yyvsp[0].interm).param.type); context->checkOutParameterIsNotSampler((yylsp[0]), (yyvsp[-1].interm.qualifier), *(yyvsp[0].interm).param.type);
context->paramErrorCheck((yylsp[0]), EvqTemporary, (yyvsp[-1].interm.qualifier), (yyval.interm).param.type); context->checkIsParameterQualifierValid((yylsp[0]), EvqTemporary, (yyvsp[-1].interm.qualifier), (yyval.interm).param.type);
} }
break; break;
...@@ -3477,7 +3476,7 @@ yyreduce: ...@@ -3477,7 +3476,7 @@ yyreduce:
{ {
VERTEX_ONLY("attribute", (yylsp[0])); VERTEX_ONLY("attribute", (yylsp[0]));
ES2_ONLY("attribute", (yylsp[0])); ES2_ONLY("attribute", (yylsp[0]));
context->globalErrorCheck((yylsp[0]), context->symbolTable.atGlobalLevel(), "attribute"); context->checkIsAtGlobalLevel((yylsp[0]), "attribute");
(yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yylsp[0])); (yyval.interm.type).setBasic(EbtVoid, EvqAttribute, (yylsp[0]));
} }
...@@ -3487,7 +3486,7 @@ yyreduce: ...@@ -3487,7 +3486,7 @@ yyreduce:
{ {
ES2_ONLY("varying", (yylsp[0])); ES2_ONLY("varying", (yylsp[0]));
context->globalErrorCheck((yylsp[0]), context->symbolTable.atGlobalLevel(), "varying"); context->checkIsAtGlobalLevel((yylsp[0]), "varying");
if (context->getShaderType() == GL_VERTEX_SHADER) if (context->getShaderType() == GL_VERTEX_SHADER)
(yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[0])); (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[0]));
else else
...@@ -3500,7 +3499,7 @@ yyreduce: ...@@ -3500,7 +3499,7 @@ yyreduce:
{ {
ES2_ONLY("varying", (yylsp[-1])); ES2_ONLY("varying", (yylsp[-1]));
context->globalErrorCheck((yylsp[-1]), context->symbolTable.atGlobalLevel(), "invariant varying"); context->checkIsAtGlobalLevel((yylsp[-1]), "invariant varying");
if (context->getShaderType() == GL_VERTEX_SHADER) if (context->getShaderType() == GL_VERTEX_SHADER)
(yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[-1])); (yyval.interm.type).setBasic(EbtVoid, EvqVaryingOut, (yylsp[-1]));
else else
...@@ -3562,7 +3561,7 @@ yyreduce: ...@@ -3562,7 +3561,7 @@ yyreduce:
case 138: case 138:
{ {
context->es3InvariantErrorCheck((yyvsp[0].interm.type).qualifier, (yylsp[-1])); context->checkInvariantIsOutVariableES3((yyvsp[0].interm.type).qualifier, (yylsp[-1]));
(yyval.interm.type).setBasic(EbtVoid, (yyvsp[0].interm.type).qualifier, (yylsp[0])); (yyval.interm.type).setBasic(EbtVoid, (yyvsp[0].interm.type).qualifier, (yylsp[0]));
(yyval.interm.type).invariant = true; (yyval.interm.type).invariant = true;
} }
...@@ -3572,7 +3571,7 @@ yyreduce: ...@@ -3572,7 +3571,7 @@ yyreduce:
case 139: case 139:
{ {
context->es3InvariantErrorCheck((yyvsp[0].interm.type).qualifier, (yylsp[-2])); context->checkInvariantIsOutVariableES3((yyvsp[0].interm.type).qualifier, (yylsp[-2]));
(yyval.interm.type) = context->joinInterpolationQualifiers((yylsp[-1]), (yyvsp[-1].interm.type).qualifier, (yylsp[0]), (yyvsp[0].interm.type).qualifier); (yyval.interm.type) = context->joinInterpolationQualifiers((yylsp[-1]), (yyvsp[-1].interm.type).qualifier, (yylsp[0]), (yyvsp[0].interm.type).qualifier);
(yyval.interm.type).invariant = true; (yyval.interm.type).invariant = true;
} }
...@@ -3641,7 +3640,7 @@ yyreduce: ...@@ -3641,7 +3640,7 @@ yyreduce:
case 145: case 145:
{ {
context->globalErrorCheck((yylsp[0]), context->symbolTable.atGlobalLevel(), "uniform"); context->checkIsAtGlobalLevel((yylsp[0]), "uniform");
(yyval.interm.type).qualifier = EvqUniform; (yyval.interm.type).qualifier = EvqUniform;
} }
...@@ -3654,7 +3653,7 @@ yyreduce: ...@@ -3654,7 +3653,7 @@ yyreduce:
if ((yyval.interm.type).precision == EbpUndefined) { if ((yyval.interm.type).precision == EbpUndefined) {
(yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).type); (yyval.interm.type).precision = context->symbolTable.getDefaultPrecision((yyvsp[0].interm.type).type);
context->precisionErrorCheck((yylsp[0]), (yyval.interm.type).precision, (yyvsp[0].interm.type).type); context->checkPrecisionSpecified((yylsp[0]), (yyval.interm.type).precision, (yyvsp[0].interm.type).type);
} }
} }
...@@ -3769,10 +3768,9 @@ yyreduce: ...@@ -3769,10 +3768,9 @@ yyreduce:
{ {
(yyval.interm.type) = (yyvsp[-3].interm.type); (yyval.interm.type) = (yyvsp[-3].interm.type);
if (!context->arrayTypeErrorCheck((yylsp[-2]), (yyvsp[-3].interm.type))) if (!context->checkIsValidTypeForArray((yylsp[-2]), (yyvsp[-3].interm.type)))
{ {
int size; unsigned int size = context->checkIsValidArraySize((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode));
context->arraySizeErrorCheck((yylsp[-2]), (yyvsp[-1].interm.intermTypedNode), size);
(yyval.interm.type).setArraySize(size); (yyval.interm.type).setArraySize(size);
} }
} }
...@@ -4310,7 +4308,7 @@ yyreduce: ...@@ -4310,7 +4308,7 @@ yyreduce:
case 215: case 215:
{ {
context->reservedErrorCheck((yylsp[0]), *(yyvsp[0].lex).string); context->checkIsNotReserved((yylsp[0]), *(yyvsp[0].lex).string);
TType* type = new TType(EbtVoid, EbpUndefined); TType* type = new TType(EbtVoid, EbpUndefined);
(yyval.interm.field) = new TField(type, (yyvsp[0].lex).string, (yylsp[0])); (yyval.interm.field) = new TField(type, (yyvsp[0].lex).string, (yylsp[0]));
...@@ -4321,11 +4319,10 @@ yyreduce: ...@@ -4321,11 +4319,10 @@ yyreduce:
case 216: case 216:
{ {
context->reservedErrorCheck((yylsp[-3]), *(yyvsp[-3].lex).string); context->checkIsNotReserved((yylsp[-3]), *(yyvsp[-3].lex).string);
TType* type = new TType(EbtVoid, EbpUndefined); TType* type = new TType(EbtVoid, EbpUndefined);
int size; unsigned int size = context->checkIsValidArraySize((yylsp[-1]), (yyvsp[-1].interm.intermTypedNode));
context->arraySizeErrorCheck((yylsp[-1]), (yyvsp[-1].interm.intermTypedNode), size);
type->setArraySize(size); type->setArraySize(size);
(yyval.interm.field) = new TField(type, (yyvsp[-3].lex).string, (yylsp[-3])); (yyval.interm.field) = new TField(type, (yyvsp[-3].lex).string, (yylsp[-3]));
...@@ -4516,7 +4513,7 @@ yyreduce: ...@@ -4516,7 +4513,7 @@ yyreduce:
case 244: case 244:
{ {
context->boolErrorCheck((yylsp[-4]), (yyvsp[-2].interm.intermTypedNode)); context->checkIsScalarBool((yylsp[-4]), (yyvsp[-2].interm.intermTypedNode));
(yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4])); (yyval.interm.intermNode) = context->intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yylsp[-4]));
} }
...@@ -4575,7 +4572,7 @@ yyreduce: ...@@ -4575,7 +4572,7 @@ yyreduce:
{ {
(yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
context->boolErrorCheck((yyvsp[0].interm.intermTypedNode)->getLine(), (yyvsp[0].interm.intermTypedNode)); context->checkIsScalarBool((yyvsp[0].interm.intermTypedNode)->getLine(), (yyvsp[0].interm.intermTypedNode));
} }
break; break;
...@@ -4584,7 +4581,7 @@ yyreduce: ...@@ -4584,7 +4581,7 @@ yyreduce:
{ {
TIntermNode *intermNode; TIntermNode *intermNode;
context->boolErrorCheck((yylsp[-2]), (yyvsp[-3].interm.type)); context->checkIsScalarBool((yylsp[-2]), (yyvsp[-3].interm.type));
if (!context->executeInitializer((yylsp[-2]), *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), (yyvsp[0].interm.intermTypedNode), &intermNode)) if (!context->executeInitializer((yylsp[-2]), *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), (yyvsp[0].interm.intermTypedNode), &intermNode))
(yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode);
...@@ -4620,7 +4617,7 @@ yyreduce: ...@@ -4620,7 +4617,7 @@ yyreduce:
case 256: case 256:
{ {
context->boolErrorCheck((yylsp[0]), (yyvsp[-2].interm.intermTypedNode)); context->checkIsScalarBool((yylsp[0]), (yyvsp[-2].interm.intermTypedNode));
(yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, (yyvsp[-5].interm.intermNode), (yylsp[-4])); (yyval.interm.intermNode) = context->intermediate.addLoop(ELoopDoWhile, 0, (yyvsp[-2].interm.intermTypedNode), 0, (yyvsp[-5].interm.intermNode), (yylsp[-4]));
context->decrLoopNestingLevel(); context->decrLoopNestingLevel();
......
...@@ -504,7 +504,7 @@ void GetVariableTraverser::traverse(const TType &type, ...@@ -504,7 +504,7 @@ void GetVariableTraverser::traverse(const TType &type,
VarT variable; VarT variable;
variable.name = name.c_str(); variable.name = name.c_str();
variable.arraySize = static_cast<unsigned int>(type.getArraySize()); variable.arraySize = type.getArraySize();
if (!structure) if (!structure)
{ {
......
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