#ifdef MEASURE_MEMORY
GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters));
+ printf("Working set size: %d\n", counters.WorkingSetSize);
}
#endif
--- /dev/null
+#version 130
+
+float gu[];
+float g4[4];
+float g5[5];
+
+uniform int a;
+
+float[4] foo(float a[5])
+{
+ return float[](a[0], a[1], a[2], a[3]);
+}
+
+void bar(float[5]) {}
+
+void main()
+{
+ {
+ float gu[2]; // okay, new scope
+
+ gu[2] = 4.0; // ERROR, overflow
+ }
+
+ gu[2] = 4.0; // okay
+
+ gu[3] = 3.0;
+ gu[a] = 5.0; // ERROR
+
+ g4 = foo(g5);
+ g5 = g4; // ERROR
+ gu = g4; // ERROR
+
+ foo(gu); // ERROR
+ bar(g5);
+
+ if (float[4](1.0, 2.0, 3.0, 4.0) == g4)
+ gu[0] = 2.0;
+
+ float u[];
+ u[2] = 3.0; // okay
+ float u[5];
+ u[5] = 5.0; // ERROR
+ foo(u); // okay
+
+ gl_FragData[1000] = vec4(1.0); // ERROR
+ gl_FragData[-1] = vec4(1.0); // ERROR
+ gl_FragData[3] = vec4(1.0);
+
+ const int ca[] = int[](3, 2);
+ int sum = ca[0];
+ sum += ca[1];
+ sum += ca[2]; // ERROR
+
+ const int ca3[3] = int[](3, 2); // ERROR
+ int ica[] = int[](3, 2);
+ int ica3[3] = int[](3, 2); // ERROR
+}
--- /dev/null
+#version 100
+
+float gu[];
+float g4[4];
+float g5[5];
+
+uniform int a;
+
+float[4] foo(float[5] a) // ERROR // ERROR
+{
+ return float[](a[0], a[1], a[2], a[3]); // ERROR
+}
+
+void bar(float[5]) {}
+
+void main()
+{
+ {
+ float gu[2]; // okay, new scope
+
+ gu[2] = 4.0; // ERROR, overflow
+ }
+
+ gu[2] = 4.0; // okay
+
+ gu[3] = 3.0;
+ gu[a] = 5.0; // ERROR
+
+ g4 = foo(g5);
+ g5 = g4; // ERROR
+ gu = g4; // ERROR
+
+ foo(gu); // ERROR
+ bar(g5);
+
+ if (float[4](1.0, 2.0, 3.0, 4.0) == g4) // ERROR
+ gu[0] = 2.0;
+
+ float u[];
+ u[2] = 3.0; // okay
+ float u[5];
+ u[5] = 5.0; // ERROR
+ foo(u); // okay
+
+ gl_FragData[1000] = vec4(1.0); // ERROR
+ gl_FragData[-1] = vec4(1.0); // ERROR
+ gl_FragData[3] = vec4(1.0);
+}
cppNest.vert
cppComplexExpr.vert
pointCoord.frag
+array.frag
+array100.frag
\ No newline at end of file
EvqLast,
};
-//
-// This is just for debug print out, carried along with the definitions above.
-//
+// These will show up in error messages
__inline const char* getStorageQualifierString(TStorageQualifier q)
{
switch (q) {
- case EvqTemporary: return "Temporary"; break;
- case EvqGlobal: return "Global"; break;
+ case EvqTemporary: return "temporary"; break;
+ case EvqGlobal: return "global"; break;
case EvqConst: return "const"; break;
case EvqConstReadOnly: return "const (read only)"; break;
case EvqAttribute: return "attribute"; break;
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
- case EvqPosition: return "Position"; break;
- case EvqPointSize: return "PointSize"; break;
- case EvqClipVertex: return "ClipVertex"; break;
- case EvqFace: return "FrontFacing"; break;
- case EvqFragCoord: return "FragCoord"; break;
- case EvqPointCoord: return "PointCoord"; break;
- case EvqFragColor: return "FragColor"; break;
- case EvqFragDepth: return "FragDepth"; break;
+ case EvqPosition: return "gl_Position"; break;
+ case EvqPointSize: return "gl_PointSize"; break;
+ case EvqClipVertex: return "gl_ClipVertex"; break;
+ case EvqFace: return "gl_FrontFacing"; break;
+ case EvqFragCoord: return "gl_FragCoord"; break;
+ case EvqPointCoord: return "gl_PointCoord"; break;
+ case EvqFragColor: return "fragment out"; break;
+ case EvqFragDepth: return "gl_FragDepth"; break;
default: return "unknown qualifier";
}
}
}
//
+// TODO: TArraySizes memory: This could be replaced by something smaller.
+// Almost all arrays could be handled by two sizes each fitting
+// in 16 bits, needing a real vector only in the cases where there
+// are more than 3 sizes or a size needing more than 16 bits.
+//
+// The type is a pointer, so that it can be non-allocated and zero
+// for the vast majority of non-array types. Note that means if it
+// is used, it will be containing at least one size.
+
+typedef TVector<int>* TArraySizes;
+
+inline TArraySizes NewPoolTArraySizes()
+{
+ void* memory = GlobalPoolAllocator.allocate(sizeof(TVector<int>));
+ return new(memory) TVector<int>;
+}
+
+//
// This is a workaround for a problem with the yacc stack, It can't have
// types that it thinks have non-trivial constructors. It should
// just be used while recognizing the grammar, not anything else. Pointers
int vectorSize : 4;
int matrixCols : 4;
int matrixRows : 4;
- bool array;
- int arraySize;
- TType* userDef;
+ TArraySizes arraySizes;
+ const TType* userDef;
int line;
void initType(int ln = 0)
vectorSize = 1;
matrixRows = 0;
matrixCols = 0;
- array = false;
- arraySize = 0;
+ arraySizes = 0;
userDef = 0;
line = ln;
}
void setVector(int s)
{
+ matrixRows = 0;
+ matrixCols = 0;
vectorSize = s;
}
matrixCols = c;
vectorSize = 0;
}
-
- void setArray(bool a, int s = 0)
- {
- array = a;
- arraySize = s;
- }
};
typedef std::map<TTypeList*, TTypeList*> TStructureMap;
public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
explicit TType(TBasicType t, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0) :
- type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), array(false), arraySize(0),
+ type(t), vectorSize(vs), matrixCols(mc), matrixRows(mr), arraySizes(0),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0),
fieldName(0), mangled(0), typeName(0)
{
qualifier.precision = EpqNone;
}
explicit TType(const TPublicType &p) :
- type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), array(p.array), arraySize(p.arraySize),
+ type(p.type), vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), arraySizes(p.arraySizes),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
{
qualifier = p.qualifier;
}
}
explicit TType(TTypeList* userDef, const TString& n) :
- type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), array(false), arraySize(0),
+ type(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), arraySizes(0),
structure(userDef), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0)
{
qualifier.storage = EvqTemporary;
vectorSize = copyOf.vectorSize;
matrixCols = copyOf.matrixCols;
matrixRows = copyOf.matrixRows;
- array = copyOf.array;
- arraySize = copyOf.arraySize;
-
+
+ if (copyOf.arraySizes) {
+ arraySizes = NewPoolTArraySizes();
+ *arraySizes = *copyOf.arraySizes;
+ } else
+ arraySizes = 0;
+
TStructureMapIterator iter;
if (copyOf.structure) {
if ((iter = remapper.find(structure)) == remapper.end()) {
virtual void dereference()
{
- if (array) {
- array = false;
- arraySize = 0;
+ if (arraySizes) {
+ arraySizes = 0;
maxArraySize = 0;
} else if (matrixCols > 0) {
vectorSize = matrixRows;
vectorSize = 1;
}
- virtual void setElementType(TBasicType t, int s, int mc, int mr, TType* userDef)
+ virtual void setElementType(TBasicType t, int s, int mc, int mr, const TType* userDef)
{
type = t;
vectorSize = s;
virtual int getMatrixRows() const { return matrixRows; }
virtual bool isMatrix() const { return matrixCols ? true : false; }
- virtual bool isArray() const { return array ? true : false; }
- int getArraySize() const { return arraySize; }
- void setArraySize(int s) { array = true; arraySize = s; }
+ virtual bool isArray() const { return arraySizes != 0; }
+ int getArraySize() const { return arraySizes->front(); }
+ void setArraySizes(TArraySizes s) {
+ // copy; we don't want distinct types sharing the same descriptor
+ if (! arraySizes)
+ arraySizes = NewPoolTArraySizes();
+ *arraySizes = *s;
+ }
+ void changeArraySize(int s) { arraySizes->front() = s; }
void setMaxArraySize (int s) { maxArraySize = s; }
int getMaxArraySize () const { return maxArraySize; }
void setArrayInformationType(TType* t) { arrayInformationType = t; }
vectorSize == right.vectorSize &&
matrixCols == right.matrixCols &&
matrixRows == right.matrixRows &&
- array == right.array && (!array || arraySize == right.arraySize) &&
+ (arraySizes == 0 && right.arraySizes == 0 || (arraySizes && right.arraySizes && *arraySizes == *right.arraySizes)) &&
structure == right.structure;
// don't check the qualifier, it's not ever what's being sought after
}
int vectorSize : 4;
int matrixCols : 4;
int matrixRows : 4;
- unsigned int array : 1;
TQualifier qualifier;
- int arraySize;
+ TArraySizes arraySizes;
TTypeList* structure; // 0 unless this is a struct
mutable int structureSize;
void TBuiltIns::initialize(const TBuiltInResource &resources)
{
//
- // Initialize all the built-in strings for parsing.
+ // Initialize the context-dependent (resource-dependent) built-in strings for parsing.
//
TString StandardUniforms;
case EShLangFragment: {
// Set up gl_FragData. The array size.
TType fragData(EbtFloat, EvqFragColor, 4);
- fragData.setArraySize(resources.maxDrawBuffers);
+ TArraySizes arraySizes = NewPoolTArraySizes();
+ arraySizes->push_back(resources.maxDrawBuffers);
+ fragData.setArraySizes(arraySizes);
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
}
break;
if (constType)
type->getQualifier().storage = EvqConst;
- if (type->isArray() && type->getArraySize() != function.getParamCount()) {
- error(line, "array constructor needs one argument per array element", "constructor", "");
- return true;
+ if (type->isArray()) {
+ if (type->getArraySize() == 0) {
+ // auto adapt the constructor type to the number of arguments
+ type->changeArraySize(function.getParamCount());
+ } else if (type->getArraySize() != function.getParamCount()) {
+ error(line, "array constructor needs one argument per array element", "constructor", "");
+ return true;
+ }
}
if (arrayArg && op != EOpConstructStruct) {
//
bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
{
- if (pType.type != EbtBool || pType.array || pType.matrixCols > 1 || (pType.vectorSize > 1)) {
+ if (pType.type != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) {
error(line, "boolean expression expected", "", "");
return true;
}
return false;
}
-bool TParseContext::containsSampler(TType& type)
+bool TParseContext::containsSampler(const TType& type)
{
if (IsSampler(type.getBasicType()))
return true;
variable = new TVariable(&identifier, TType(type));
- if (type.arraySize)
- variable->getType().setArraySize(type.arraySize);
-
if (! symbolTable.insert(*variable)) {
delete variable;
error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
TType* t = variable->getArrayInformationType();
while (t != 0) {
- if (t->getMaxArraySize() > type.arraySize) {
+ if (t->getMaxArraySize() > type.arraySizes->front()) {
error(line, "higher index value already used for the array", identifier.c_str(), "");
return true;
}
- t->setArraySize(type.arraySize);
+ t->setArraySizes(type.arraySizes);
t = t->getArrayInformationType();
}
- if (type.arraySize)
- variable->getType().setArraySize(type.arraySize);
+ variable->getType().setArraySizes(type.arraySizes);
}
if (voidErrorCheck(line, identifier, type))
error(line, " cannot initialize this type of qualifier ", variable->getType().getStorageQualifierString(), "");
return true;
}
+
+ // Fix arrayness if variable is unsized, getting size for initializer
+ if (initializer->getType().isArray() && initializer->getType().getArraySize() > 0 &&
+ type.isArray() && type.getArraySize() == 0)
+ type.changeArraySize(initializer->getType().getArraySize());
+
//
// test for and propagate constant
//
-
if (qualifier == EvqConst) {
if (qualifier != initializer->getType().getQualifier().storage) {
error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
TType arrayElementType = node->getType();
arrayElementType.dereference();
- if (index >= node->getType().getArraySize()) {
- error(line, "", "[", "array index out of range '%d'", index);
+ if (index >= node->getType().getArraySize() || index < 0) {
+ error(line, "", "[", "array index '%d' out of range", index);
recover();
index = 0;
}
bool structQualifierErrorCheck(int line, const TPublicType& pType);
void setDefaultPrecision(int line, TBasicType, TPrecisionQualifier);
bool parameterSamplerErrorCheck(int line, TStorageQualifier qualifier, const TType& type);
- bool containsSampler(TType& type);
+ bool containsSampler(const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type);
bool paramErrorCheck(int line, TStorageQualifier qualifier, TType* type);
void PaReservedWord();
int PaIdentOrType(TString& id, TParseContext&, TSymbol*&);
int PaParseComment(int &lineno, TParseContext&);
-void setInitialState();
+void ResetFlex();
typedef TParseContext* TParseContextPointer;
extern TParseContextPointer& GetGlobalParseContext();
GlobalParseContext = &parseContext;
- setInitialState();
-
assert(symbolTable->isEmpty() || symbolTable->atSharedBuiltInLevel());
//
// Parse the built-ins. This should only happen once per
- // language symbol table.
+ // language symbol table when no 'resources' are passed in.
//
// Push the symbol table to give it an initial scope. This
// push should not have a corresponding pop, so that built-ins
//
symbolTable->push();
+
//Initialize the Preprocessor
int ret = InitPreprocessor();
infoSink.info.message(EPrefixInternalError, "Unable to intialize the Preprocessor");
return false;
}
+
+ ResetFlex();
for (TBuiltInStrings::iterator i = BuiltInStrings[parseContext.language].begin();
i != BuiltInStrings[parseContext.language].end(); ++i) {
return false;
}
}
+ FinalizePreprocessor();
if (resources) {
IdentifyBuiltIns(parseContext.language, *symbolTable, *resources);
- } else {
+ } else {
IdentifyBuiltIns(parseContext.language, *symbolTable);
}
-
- FinalizePreprocessor();
-
return true;
}
TIntermediate intermediate(compiler->infoSink);
TSymbolTable symbolTable(SymbolTables[compiler->getLanguage()]);
+ // Add built-in symbols that are potentially context dependent;
+ // they get popped again further down.
GenerateBuiltInSymbolTable(resources, compiler->infoSink, &symbolTable, compiler->getLanguage());
TParseContext parseContext(symbolTable, intermediate, compiler->getLanguage(), compiler->infoSink, defaultVersion);
GlobalParseContext = &parseContext;
- setInitialState();
+ ResetFlex();
+ InitPreprocessor();
- InitPreprocessor();
//
// Parse the application's shaders. All the following symbol table
// work will be throw-away, so push a new allocation scope that can
mangledName += static_cast<char>('0' + getMatrixRows());
}
- if (isArray()) {
+ if (arraySizes) {
const int maxSize = 10;
char buf[maxSize];
- sprintf_s(buf, maxSize, "%d", arraySize);
+ sprintf_s(buf, maxSize, "%d", arraySizes->front());
mangledName += '[';
mangledName += buf;
mangledName += ']';
\r
} // extern "C"\r
\r
-void setInitialState()\r
+void ResetFlex()\r
{\r
yy_start = 1;\r
}\r
TParameter param;\r
TTypeLine typeLine;\r
TTypeList* typeList;\r
- TVector<int>* intVector;\r
+ TArraySizes arraySizes;\r
};\r
} interm;\r
}\r
if (parseContext.arraySetMaxSize($1->getAsSymbolNode(), $1->getTypePointer(), 0, false, $2.line))\r
parseContext.recover();\r
}\r
- } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize()) {\r
+ } else if ( $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() >= $1->getType().getArraySize() ||\r
+ $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst() < 0) {\r
parseContext.error($2.line, "", "[", "array index out of range '%d'", $3->getAsConstantUnion()->getUnionArrayPointer()->getIConst());\r
parseContext.recover();\r
}\r
TType newType = $1->getType();\r
newType.dereference();\r
$$->setType(newType);\r
- //?? why didn't the code above get the type right?\r
- //?? write a deference test\r
+ //?? why wouldn't the code above get the type right?\r
+ //?? write a dereference test\r
}\r
}\r
| function_call {\r
}\r
}\r
} else {\r
- //?? fix message\r
- parseContext.error($2.line, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str(), "");\r
+ parseContext.error($2.line, " dot operator requires structure, array, vector, or matrix on left hand side", $3.string->c_str(), "");\r
parseContext.recover();\r
$$ = $1;\r
}\r
TOperator op = fnCall->getBuiltInOp();\r
if (op == EOpArrayLength) {\r
// TODO: check for no arguments to .length()\r
- if ($1.intermNode->getAsTyped() == 0 || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) {\r
+ int length;\r
+ if ($1.intermNode->getAsTyped() == 0 || ! $1.intermNode->getAsTyped()->getType().isArray() || $1.intermNode->getAsTyped()->getType().getArraySize() == 0) {\r
parseContext.error($1.line, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");\r
parseContext.recover();\r
- }\r
+ length = 1;\r
+ } else\r
+ length = $1.intermNode->getAsTyped()->getType().getArraySize();\r
\r
constUnion *unionArray = new constUnion[1];\r
- unionArray->setIConst($1.intermNode->getAsTyped()->getType().getArraySize());\r
+ unionArray->setIConst(length);\r
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);\r
} else if (op != EOpNull) {\r
//\r
$$.function = 0;\r
$$.intermNode = 0;\r
\r
- if ($1.array) {\r
- parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");\r
+ if ($1.arraySizes) {\r
+ parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed constructor");\r
+ parseContext.profileRequires($1.line, EEsProfile, 300, "GL_3DL_array_objects", "arrayed constructor");\r
}\r
\r
$1.qualifier.precision = EpqNone;\r
parameter_declarator\r
// Type + name\r
: type_specifier IDENTIFIER {\r
+ if ($1.arraySizes) {\r
+ parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
+ parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");\r
+ }\r
if ($1.type == EbtVoid) {\r
parseContext.error($2.line, "illegal use of type 'void'", $2.string->c_str(), "");\r
parseContext.recover();\r
$$.param = param;\r
}\r
| type_specifier IDENTIFIER array_specifier {\r
- if (parseContext.arraySizeRequiredErrorCheck($3.line, $3.intVector->front()))\r
+ if ($1.arraySizes) {\r
+ parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
+ parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");\r
+ }\r
+\r
+ if (parseContext.arraySizeRequiredErrorCheck($3.line, $3.arraySizes->front()))\r
parseContext.recover();\r
\r
if (parseContext.reservedErrorCheck($2.line, *$2.string))\r
parseContext.recover();\r
\r
- $1.setArray(true, $3.intVector->front());\r
+ $1.arraySizes = $3.arraySizes;\r
\r
TParameter param = { $2.string, new TType($1)};\r
$$.line = $2.line;\r
if (parseContext.arrayQualifierErrorCheck($4.line, $1.type))\r
parseContext.recover();\r
else {\r
- $1.type.setArray(true, $4.intVector->front());\r
+ $1.type.arraySizes = $4.arraySizes;\r
TVariable* variable;\r
if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))\r
parseContext.recover();\r
if (parseContext.arrayQualifierErrorCheck($4.line, $1.type))\r
parseContext.recover();\r
else {\r
- $1.type.setArray(true, $4.intVector->front());\r
+ $1.type.arraySizes = $4.arraySizes;\r
if (parseContext.arrayErrorCheck($4.line, *$3.string, $1.type, variable))\r
parseContext.recover();\r
}\r
if (parseContext.arrayQualifierErrorCheck($3.line, $1))\r
parseContext.recover();\r
else {\r
- $1.setArray(true, $3.intVector->front());\r
+ $1.arraySizes = $3.arraySizes;\r
TVariable* variable;\r
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))\r
parseContext.recover();\r
if (parseContext.arrayQualifierErrorCheck($3.line, $1))\r
parseContext.recover();\r
else {\r
- $1.setArray(true, $3.intVector->front());\r
+ $1.arraySizes = $3.arraySizes;\r
if (parseContext.arrayErrorCheck($3.line, *$2.string, $1, variable))\r
parseContext.recover();\r
}\r
: type_specifier {\r
$$ = $1;\r
\r
- if ($1.array) {\r
- parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");\r
+ if ($1.arraySizes) {\r
+ parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
+ parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");\r
}\r
}\r
| type_qualifier type_specifier {\r
- if ($2.array)\r
- parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "array");\r
+ if ($2.arraySizes) {\r
+ parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
+ parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");\r
+ }\r
\r
- if ($2.array && parseContext.arrayQualifierErrorCheck($2.line, $1)) {\r
+ if ($2.arraySizes && parseContext.arrayQualifierErrorCheck($2.line, $1)) {\r
parseContext.recover();\r
- $2.setArray(false);\r
+ $2.arraySizes = 0;\r
}\r
\r
if ($1.qualifier.storage == EvqAttribute &&\r
| type_specifier_nonarray array_specifier {\r
$$ = $1;\r
$$.qualifier.precision = parseContext.defaultPrecision[$$.type];\r
- $$.setArray(true, $2.intVector->front());\r
+ $$.arraySizes = $2.arraySizes;\r
}\r
;\r
\r
array_specifier\r
: LEFT_BRACKET RIGHT_BRACKET {\r
$$.line = $1.line;\r
- $$.intVector = new TVector<int>;\r
- $$.intVector->push_back(0);\r
+ $$.arraySizes = NewPoolTArraySizes();\r
+ $$.arraySizes->push_back(0);\r
}\r
| LEFT_BRACKET constant_expression RIGHT_BRACKET {\r
$$.line = $1.line;\r
- $$.intVector = new TVector<int>;\r
+ $$.arraySizes = NewPoolTArraySizes();\r
\r
int size;\r
if (parseContext.arraySizeErrorCheck($2->getLine(), $2, size))\r
parseContext.recover();\r
- $$.intVector->push_back(size);\r
+ $$.arraySizes->push_back(size);\r
}\r
| array_specifier LEFT_BRACKET RIGHT_BRACKET {\r
$$ = $1;\r
- $$.intVector->push_back(0);\r
+ $$.arraySizes->push_back(0);\r
}\r
| array_specifier LEFT_BRACKET constant_expression RIGHT_BRACKET {\r
$$ = $1;\r
int size;\r
if (parseContext.arraySizeErrorCheck($3->getLine(), $3, size))\r
parseContext.recover();\r
- $$.intVector->push_back(size);\r
+ $$.arraySizes->push_back(size);\r
}\r
;\r
\r
// This is for user defined type names. The lexical phase looked up the\r
// type.\r
//\r
- TType& structure = static_cast<TVariable*>($1.symbol)->getType();\r
+ const TType& structure = static_cast<const TVariable*>($1.symbol)->getType();\r
$$.init($1.line, parseContext.symbolTable.atGlobalLevel());\r
$$.type = EbtStruct;\r
$$.userDef = &structure;\r
\r
struct_declaration\r
: type_specifier struct_declarator_list SEMICOLON {\r
+ if ($1.arraySizes) {\r
+ parseContext.profileRequires($1.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
+ parseContext.profileRequires($1.line, EEsProfile, 300, 0, "arrayed type");\r
+ }\r
+\r
$$ = $2;\r
\r
if (parseContext.voidErrorCheck($1.line, (*$2)[0].type->getFieldName(), $1)) {\r
//\r
(*$$)[i].type->setElementType($1.type, $1.vectorSize, $1.matrixCols, $1.matrixRows, $1.userDef);\r
\r
- if ($1.array)\r
- (*$$)[i].type->setArraySize($1.arraySize);\r
+ if ($1.arraySizes)\r
+ (*$$)[i].type->setArraySizes($1.arraySizes);\r
if ($1.userDef)\r
(*$$)[i].type->setTypeName($1.userDef->getTypeName());\r
}\r
}\r
| type_qualifier type_specifier struct_declarator_list SEMICOLON {\r
+ if ($2.arraySizes) {\r
+ parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");\r
+ parseContext.profileRequires($2.line, EEsProfile, 300, 0, "arrayed type");\r
+ }\r
+\r
$$ = $3;\r
\r
if (parseContext.voidErrorCheck($2.line, (*$3)[0].type->getFieldName(), $2)) {\r
//\r
(*$$)[i].type->setElementType($2.type, $2.vectorSize, $2.matrixCols, $2.matrixRows, $2.userDef);\r
\r
- if ($2.array)\r
- (*$$)[i].type->setArraySize($2.arraySize);\r
+ if ($2.arraySizes)\r
+ (*$$)[i].type->setArraySizes($2.arraySizes);\r
if ($2.userDef)\r
(*$$)[i].type->setTypeName($2.userDef->getTypeName());\r
}\r
$$.type = new TType(EbtVoid);\r
$$.line = $1.line;\r
$$.type->setFieldName(*$1.string);\r
- $$.type->setArraySize($2.intVector->front());\r
+ $$.type->setArraySizes($2.arraySizes);\r
}\r
;\r
\r
if (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal)
p += sprintf_s(p, end - p, "%s ", getStorageQualifierString());
- if (array)
- p += sprintf_s(p, end - p, "array of ");
+ if (arraySizes) {
+ if (arraySizes->front() == 0)
+ p += sprintf_s(p, end - p, "unsized array of ");
+ else
+ p += sprintf_s(p, end - p, "%d-element array of ", arraySizes->front());
+ }
if (qualifier.precision != EpqNone)
p += sprintf_s(p, end - p, "%s ", getPrecisionQualifierString());
if (matrixCols > 0)