GLSL: Implement correct semantic checking for run-time sized arrays.
This commit is contained in:
@@ -390,7 +390,7 @@ TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIn
|
||||
error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable");
|
||||
else {
|
||||
// it is okay for a run-time sized array
|
||||
if (base->getType().getQualifier().storage != EvqBuffer)
|
||||
if (!isRuntimeSizable(*base))
|
||||
error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable");
|
||||
}
|
||||
base->getWritableType().setArrayVariablyIndexed();
|
||||
@@ -1235,7 +1235,7 @@ TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction
|
||||
if (length == 0) {
|
||||
if (intermNode->getAsSymbolNode() && isIoResizeArray(type))
|
||||
error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
|
||||
else if (type.getQualifier().isUniformOrBuffer()) {
|
||||
else if (isRuntimeLength(*intermNode->getAsTyped())) {
|
||||
// Create a unary op and let the back end handle it
|
||||
return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt));
|
||||
} else
|
||||
@@ -3268,6 +3268,31 @@ void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifie
|
||||
checkIoArraysConsistency(loc);
|
||||
}
|
||||
|
||||
// Policy decision for whether a node could potentially be sized at runtime.
|
||||
bool TParseContext::isRuntimeSizable(const TIntermTyped& base) const
|
||||
{
|
||||
const TType& type = base.getType();
|
||||
if (type.getQualifier().storage == EvqBuffer) {
|
||||
// in a buffer block
|
||||
const TIntermBinary* binary = base.getAsBinaryNode();
|
||||
if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) {
|
||||
// is it the last member?
|
||||
const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
|
||||
const int memberCount = (int)binary->getLeft()->getType().getStruct()->size();
|
||||
if (index == memberCount - 1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Policy decision for whether a run-time .length() is allowed.
|
||||
bool TParseContext::isRuntimeLength(const TIntermTyped& base) const
|
||||
{
|
||||
return isRuntimeSizable(base);
|
||||
}
|
||||
|
||||
// Returns true if the first argument to the #line directive is the line number for the next line.
|
||||
//
|
||||
// Desktop, pre-version 3.30: "After processing this directive
|
||||
|
||||
@@ -427,6 +427,8 @@ protected:
|
||||
TVariable* makeInternalVariable(const char* name, const TType&) const;
|
||||
TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
|
||||
void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
|
||||
bool isRuntimeSizable(const TIntermTyped&) const;
|
||||
bool isRuntimeLength(const TIntermTyped&) const;
|
||||
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
|
||||
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
|
||||
void finish() override;
|
||||
|
||||
Reference in New Issue
Block a user