Home | History | Annotate | Download | only in translator
      1 //
      2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 #include "compiler/translator/ParseContext.h"
      8 
      9 #include <stdarg.h>
     10 #include <stdio.h>
     11 
     12 #include "compiler/translator/glslang.h"
     13 #include "compiler/preprocessor/SourceLocation.h"
     14 
     15 ///////////////////////////////////////////////////////////////////////
     16 //
     17 // Sub- vector and matrix fields
     18 //
     19 ////////////////////////////////////////////////////////////////////////
     20 
     21 //
     22 // Look at a '.' field selector string and change it into offsets
     23 // for a vector.
     24 //
     25 bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, const TSourceLoc& line)
     26 {
     27     fields.num = (int) compString.size();
     28     if (fields.num > 4) {
     29         error(line, "illegal vector field selection", compString.c_str());
     30         return false;
     31     }
     32 
     33     enum {
     34         exyzw,
     35         ergba,
     36         estpq
     37     } fieldSet[4];
     38 
     39     for (int i = 0; i < fields.num; ++i) {
     40         switch (compString[i])  {
     41         case 'x':
     42             fields.offsets[i] = 0;
     43             fieldSet[i] = exyzw;
     44             break;
     45         case 'r':
     46             fields.offsets[i] = 0;
     47             fieldSet[i] = ergba;
     48             break;
     49         case 's':
     50             fields.offsets[i] = 0;
     51             fieldSet[i] = estpq;
     52             break;
     53         case 'y':
     54             fields.offsets[i] = 1;
     55             fieldSet[i] = exyzw;
     56             break;
     57         case 'g':
     58             fields.offsets[i] = 1;
     59             fieldSet[i] = ergba;
     60             break;
     61         case 't':
     62             fields.offsets[i] = 1;
     63             fieldSet[i] = estpq;
     64             break;
     65         case 'z':
     66             fields.offsets[i] = 2;
     67             fieldSet[i] = exyzw;
     68             break;
     69         case 'b':
     70             fields.offsets[i] = 2;
     71             fieldSet[i] = ergba;
     72             break;
     73         case 'p':
     74             fields.offsets[i] = 2;
     75             fieldSet[i] = estpq;
     76             break;
     77 
     78         case 'w':
     79             fields.offsets[i] = 3;
     80             fieldSet[i] = exyzw;
     81             break;
     82         case 'a':
     83             fields.offsets[i] = 3;
     84             fieldSet[i] = ergba;
     85             break;
     86         case 'q':
     87             fields.offsets[i] = 3;
     88             fieldSet[i] = estpq;
     89             break;
     90         default:
     91             error(line, "illegal vector field selection", compString.c_str());
     92             return false;
     93         }
     94     }
     95 
     96     for (int i = 0; i < fields.num; ++i) {
     97         if (fields.offsets[i] >= vecSize) {
     98             error(line, "vector field selection out of range",  compString.c_str());
     99             return false;
    100         }
    101 
    102         if (i > 0) {
    103             if (fieldSet[i] != fieldSet[i-1]) {
    104                 error(line, "illegal - vector component fields not from the same set", compString.c_str());
    105                 return false;
    106             }
    107         }
    108     }
    109 
    110     return true;
    111 }
    112 
    113 
    114 //
    115 // Look at a '.' field selector string and change it into offsets
    116 // for a matrix.
    117 //
    118 bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, const TSourceLoc& line)
    119 {
    120     fields.wholeRow = false;
    121     fields.wholeCol = false;
    122     fields.row = -1;
    123     fields.col = -1;
    124 
    125     if (compString.size() != 2) {
    126         error(line, "illegal length of matrix field selection", compString.c_str());
    127         return false;
    128     }
    129 
    130     if (compString[0] == '_') {
    131         if (compString[1] < '0' || compString[1] > '3') {
    132             error(line, "illegal matrix field selection", compString.c_str());
    133             return false;
    134         }
    135         fields.wholeCol = true;
    136         fields.col = compString[1] - '0';
    137     } else if (compString[1] == '_') {
    138         if (compString[0] < '0' || compString[0] > '3') {
    139             error(line, "illegal matrix field selection", compString.c_str());
    140             return false;
    141         }
    142         fields.wholeRow = true;
    143         fields.row = compString[0] - '0';
    144     } else {
    145         if (compString[0] < '0' || compString[0] > '3' ||
    146             compString[1] < '0' || compString[1] > '3') {
    147             error(line, "illegal matrix field selection", compString.c_str());
    148             return false;
    149         }
    150         fields.row = compString[0] - '0';
    151         fields.col = compString[1] - '0';
    152     }
    153 
    154     if (fields.row >= matRows || fields.col >= matCols) {
    155         error(line, "matrix field selection out of range", compString.c_str());
    156         return false;
    157     }
    158 
    159     return true;
    160 }
    161 
    162 ///////////////////////////////////////////////////////////////////////
    163 //
    164 // Errors
    165 //
    166 ////////////////////////////////////////////////////////////////////////
    167 
    168 //
    169 // Track whether errors have occurred.
    170 //
    171 void TParseContext::recover()
    172 {
    173 }
    174 
    175 //
    176 // Used by flex/bison to output all syntax and parsing errors.
    177 //
    178 void TParseContext::error(const TSourceLoc& loc,
    179                           const char* reason, const char* token,
    180                           const char* extraInfo)
    181 {
    182     pp::SourceLocation srcLoc;
    183     srcLoc.file = loc.first_file;
    184     srcLoc.line = loc.first_line;
    185     diagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
    186                           srcLoc, reason, token, extraInfo);
    187 
    188 }
    189 
    190 void TParseContext::warning(const TSourceLoc& loc,
    191                             const char* reason, const char* token,
    192                             const char* extraInfo) {
    193     pp::SourceLocation srcLoc;
    194     srcLoc.file = loc.first_file;
    195     srcLoc.line = loc.first_line;
    196     diagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
    197                           srcLoc, reason, token, extraInfo);
    198 }
    199 
    200 void TParseContext::trace(const char* str)
    201 {
    202     diagnostics.writeDebug(str);
    203 }
    204 
    205 //
    206 // Same error message for all places assignments don't work.
    207 //
    208 void TParseContext::assignError(const TSourceLoc& line, const char* op, TString left, TString right)
    209 {
    210     std::stringstream extraInfoStream;
    211     extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
    212     std::string extraInfo = extraInfoStream.str();
    213     error(line, "", op, extraInfo.c_str());
    214 }
    215 
    216 //
    217 // Same error message for all places unary operations don't work.
    218 //
    219 void TParseContext::unaryOpError(const TSourceLoc& line, const char* op, TString operand)
    220 {
    221     std::stringstream extraInfoStream;
    222     extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
    223                     << " (or there is no acceptable conversion)";
    224     std::string extraInfo = extraInfoStream.str();
    225     error(line, " wrong operand type", op, extraInfo.c_str());
    226 }
    227 
    228 //
    229 // Same error message for all binary operations don't work.
    230 //
    231 void TParseContext::binaryOpError(const TSourceLoc& line, const char* op, TString left, TString right)
    232 {
    233     std::stringstream extraInfoStream;
    234     extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left
    235                     << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
    236     std::string extraInfo = extraInfoStream.str();
    237     error(line, " wrong operand types ", op, extraInfo.c_str());
    238 }
    239 
    240 bool TParseContext::precisionErrorCheck(const TSourceLoc& line, TPrecision precision, TBasicType type){
    241     if (!checksPrecisionErrors)
    242         return false;
    243     switch( type ){
    244     case EbtFloat:
    245         if( precision == EbpUndefined ){
    246             error( line, "No precision specified for (float)", "" );
    247             return true;
    248         }
    249         break;
    250     case EbtInt:
    251         if( precision == EbpUndefined ){
    252             error( line, "No precision specified (int)", "" );
    253             return true;
    254         }
    255         break;
    256     default:
    257         return false;
    258     }
    259     return false;
    260 }
    261 
    262 //
    263 // Both test and if necessary, spit out an error, to see if the node is really
    264 // an l-value that can be operated on this way.
    265 //
    266 // Returns true if the was an error.
    267 //
    268 bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIntermTyped* node)
    269 {
    270     TIntermSymbol* symNode = node->getAsSymbolNode();
    271     TIntermBinary* binaryNode = node->getAsBinaryNode();
    272 
    273     if (binaryNode) {
    274         bool errorReturn;
    275 
    276         switch(binaryNode->getOp()) {
    277         case EOpIndexDirect:
    278         case EOpIndexIndirect:
    279         case EOpIndexDirectStruct:
    280         case EOpIndexDirectInterfaceBlock:
    281             return lValueErrorCheck(line, op, binaryNode->getLeft());
    282         case EOpVectorSwizzle:
    283             errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
    284             if (!errorReturn) {
    285                 int offset[4] = {0,0,0,0};
    286 
    287                 TIntermTyped* rightNode = binaryNode->getRight();
    288                 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
    289 
    290                 for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
    291                                                p != aggrNode->getSequence().end(); p++) {
    292                     int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
    293                     offset[value]++;
    294                     if (offset[value] > 1) {
    295                         error(line, " l-value of swizzle cannot have duplicate components", op);
    296 
    297                         return true;
    298                     }
    299                 }
    300             }
    301 
    302             return errorReturn;
    303         default:
    304             break;
    305         }
    306         error(line, " l-value required", op);
    307 
    308         return true;
    309     }
    310 
    311 
    312     const char* symbol = 0;
    313     if (symNode != 0)
    314         symbol = symNode->getSymbol().c_str();
    315 
    316     const char* message = 0;
    317     switch (node->getQualifier()) {
    318     case EvqConst:          message = "can't modify a const";        break;
    319     case EvqConstReadOnly:  message = "can't modify a const";        break;
    320     case EvqAttribute:      message = "can't modify an attribute";   break;
    321     case EvqFragmentIn:     message = "can't modify an input";       break;
    322     case EvqVertexIn:       message = "can't modify an input";       break;
    323     case EvqUniform:        message = "can't modify a uniform";      break;
    324     case EvqVaryingIn:      message = "can't modify a varying";      break;
    325     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
    326     case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
    327     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
    328     default:
    329 
    330         //
    331         // Type that can't be written to?
    332         //
    333         if (node->getBasicType() == EbtVoid) {
    334             message = "can't modify void";
    335         }
    336         if (IsSampler(node->getBasicType())) {
    337             message = "can't modify a sampler";
    338         }
    339     }
    340 
    341     if (message == 0 && binaryNode == 0 && symNode == 0) {
    342         error(line, " l-value required", op);
    343 
    344         return true;
    345     }
    346 
    347 
    348     //
    349     // Everything else is okay, no error.
    350     //
    351     if (message == 0)
    352         return false;
    353 
    354     //
    355     // If we get here, we have an error and a message.
    356     //
    357     if (symNode) {
    358         std::stringstream extraInfoStream;
    359         extraInfoStream << "\"" << symbol << "\" (" << message << ")";
    360         std::string extraInfo = extraInfoStream.str();
    361         error(line, " l-value required", op, extraInfo.c_str());
    362     }
    363     else {
    364         std::stringstream extraInfoStream;
    365         extraInfoStream << "(" << message << ")";
    366         std::string extraInfo = extraInfoStream.str();
    367         error(line, " l-value required", op, extraInfo.c_str());
    368     }
    369 
    370     return true;
    371 }
    372 
    373 //
    374 // Both test, and if necessary spit out an error, to see if the node is really
    375 // a constant.
    376 //
    377 // Returns true if the was an error.
    378 //
    379 bool TParseContext::constErrorCheck(TIntermTyped* node)
    380 {
    381     if (node->getQualifier() == EvqConst)
    382         return false;
    383 
    384     error(node->getLine(), "constant expression required", "");
    385 
    386     return true;
    387 }
    388 
    389 //
    390 // Both test, and if necessary spit out an error, to see if the node is really
    391 // an integer.
    392 //
    393 // Returns true if the was an error.
    394 //
    395 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
    396 {
    397     if (node->isScalarInt())
    398         return false;
    399 
    400     error(node->getLine(), "integer expression required", token);
    401 
    402     return true;
    403 }
    404 
    405 //
    406 // Both test, and if necessary spit out an error, to see if we are currently
    407 // globally scoped.
    408 //
    409 // Returns true if the was an error.
    410 //
    411 bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
    412 {
    413     if (global)
    414         return false;
    415 
    416     error(line, "only allowed at global scope", token);
    417 
    418     return true;
    419 }
    420 
    421 //
    422 // For now, keep it simple:  if it starts "gl_", it's reserved, independent
    423 // of scope.  Except, if the symbol table is at the built-in push-level,
    424 // which is when we are parsing built-ins.
    425 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
    426 // webgl shader.
    427 //
    428 // Returns true if there was an error.
    429 //
    430 bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
    431 {
    432     static const char* reservedErrMsg = "reserved built-in name";
    433     if (!symbolTable.atBuiltInLevel()) {
    434         if (identifier.compare(0, 3, "gl_") == 0) {
    435             error(line, reservedErrMsg, "gl_");
    436             return true;
    437         }
    438         if (IsWebGLBasedSpec(shaderSpec)) {
    439             if (identifier.compare(0, 6, "webgl_") == 0) {
    440                 error(line, reservedErrMsg, "webgl_");
    441                 return true;
    442             }
    443             if (identifier.compare(0, 7, "_webgl_") == 0) {
    444                 error(line, reservedErrMsg, "_webgl_");
    445                 return true;
    446             }
    447             if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
    448                 error(line, reservedErrMsg, "css_");
    449                 return true;
    450             }
    451         }
    452         if (identifier.find("__") != TString::npos) {
    453             error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
    454             return true;
    455         }
    456     }
    457 
    458     return false;
    459 }
    460 
    461 //
    462 // Make sure there is enough data provided to the constructor to build
    463 // something of the type of the constructor.  Also returns the type of
    464 // the constructor.
    465 //
    466 // Returns true if there was an error in construction.
    467 //
    468 bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
    469 {
    470     *type = function.getReturnType();
    471 
    472     bool constructingMatrix = false;
    473     switch(op) {
    474     case EOpConstructMat2:
    475     case EOpConstructMat3:
    476     case EOpConstructMat4:
    477         constructingMatrix = true;
    478         break;
    479     default:
    480         break;
    481     }
    482 
    483     //
    484     // Note: It's okay to have too many components available, but not okay to have unused
    485     // arguments.  'full' will go to true when enough args have been seen.  If we loop
    486     // again, there is an extra argument, so 'overfull' will become true.
    487     //
    488 
    489     size_t size = 0;
    490     bool constType = true;
    491     bool full = false;
    492     bool overFull = false;
    493     bool matrixInMatrix = false;
    494     bool arrayArg = false;
    495     for (size_t i = 0; i < function.getParamCount(); ++i) {
    496         const TParameter& param = function.getParam(i);
    497         size += param.type->getObjectSize();
    498 
    499         if (constructingMatrix && param.type->isMatrix())
    500             matrixInMatrix = true;
    501         if (full)
    502             overFull = true;
    503         if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
    504             full = true;
    505         if (param.type->getQualifier() != EvqConst)
    506             constType = false;
    507         if (param.type->isArray())
    508             arrayArg = true;
    509     }
    510 
    511     if (constType)
    512         type->setQualifier(EvqConst);
    513 
    514     if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
    515         error(line, "array constructor needs one argument per array element", "constructor");
    516         return true;
    517     }
    518 
    519     if (arrayArg && op != EOpConstructStruct) {
    520         error(line, "constructing from a non-dereferenced array", "constructor");
    521         return true;
    522     }
    523 
    524     if (matrixInMatrix && !type->isArray()) {
    525         if (function.getParamCount() != 1) {
    526           error(line, "constructing matrix from matrix can only take one argument", "constructor");
    527           return true;
    528         }
    529     }
    530 
    531     if (overFull) {
    532         error(line, "too many arguments", "constructor");
    533         return true;
    534     }
    535 
    536     if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->fields().size() != function.getParamCount()) {
    537         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
    538         return true;
    539     }
    540 
    541     if (!type->isMatrix() || !matrixInMatrix) {
    542         if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
    543             (op == EOpConstructStruct && size < type->getObjectSize())) {
    544             error(line, "not enough data provided for construction", "constructor");
    545             return true;
    546         }
    547     }
    548 
    549     TIntermTyped *typed = node ? node->getAsTyped() : 0;
    550     if (typed == 0) {
    551         error(line, "constructor argument does not have a type", "constructor");
    552         return true;
    553     }
    554     if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
    555         error(line, "cannot convert a sampler", "constructor");
    556         return true;
    557     }
    558     if (typed->getBasicType() == EbtVoid) {
    559         error(line, "cannot convert a void", "constructor");
    560         return true;
    561     }
    562 
    563     return false;
    564 }
    565 
    566 // This function checks to see if a void variable has been declared and raise an error message for such a case
    567 //
    568 // returns true in case of an error
    569 //
    570 bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
    571 {
    572     if (pubType.type == EbtVoid) {
    573         error(line, "illegal use of type 'void'", identifier.c_str());
    574         return true;
    575     }
    576 
    577     return false;
    578 }
    579 
    580 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
    581 //
    582 // returns true in case of an error
    583 //
    584 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
    585 {
    586     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
    587         error(line, "boolean expression expected", "");
    588         return true;
    589     }
    590 
    591     return false;
    592 }
    593 
    594 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
    595 //
    596 // returns true in case of an error
    597 //
    598 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
    599 {
    600     if (pType.type != EbtBool || pType.isAggregate()) {
    601         error(line, "boolean expression expected", "");
    602         return true;
    603     }
    604 
    605     return false;
    606 }
    607 
    608 bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
    609 {
    610     if (pType.type == EbtStruct) {
    611         if (containsSampler(*pType.userDef)) {
    612             error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
    613 
    614             return true;
    615         }
    616 
    617         return false;
    618     } else if (IsSampler(pType.type)) {
    619         error(line, reason, getBasicString(pType.type));
    620 
    621         return true;
    622     }
    623 
    624     return false;
    625 }
    626 
    627 bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
    628 {
    629     switch (pType.qualifier)
    630     {
    631       case EvqVaryingIn:
    632       case EvqVaryingOut:
    633       case EvqAttribute:
    634       case EvqVertexIn:
    635       case EvqFragmentOut:
    636         if (pType.type == EbtStruct)
    637         {
    638             error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
    639             return true;
    640         }
    641 
    642       default: break;
    643     }
    644 
    645     if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
    646         return true;
    647 
    648     return false;
    649 }
    650 
    651 bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType)
    652 {
    653     if (pType.layoutQualifier.location != -1)
    654     {
    655         error(line, "location must only be specified for a single input or output variable", "location");
    656         return true;
    657     }
    658 
    659     return false;
    660 }
    661 
    662 bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
    663 {
    664     if ((qualifier == EvqOut || qualifier == EvqInOut) &&
    665              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
    666         error(line, "samplers cannot be output parameters", type.getBasicString());
    667         return true;
    668     }
    669 
    670     return false;
    671 }
    672 
    673 bool TParseContext::containsSampler(TType& type)
    674 {
    675     if (IsSampler(type.getBasicType()))
    676         return true;
    677 
    678     if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) {
    679         const TFieldList& fields = type.getStruct()->fields();
    680         for (unsigned int i = 0; i < fields.size(); ++i) {
    681             if (containsSampler(*fields[i]->type()))
    682                 return true;
    683         }
    684     }
    685 
    686     return false;
    687 }
    688 
    689 //
    690 // Do size checking for an array type's size.
    691 //
    692 // Returns true if there was an error.
    693 //
    694 bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
    695 {
    696     TIntermConstantUnion* constant = expr->getAsConstantUnion();
    697 
    698     if (constant == 0 || !constant->isScalarInt())
    699     {
    700         error(line, "array size must be a constant integer expression", "");
    701         return true;
    702     }
    703 
    704     unsigned int unsignedSize = 0;
    705 
    706     if (constant->getBasicType() == EbtUInt)
    707     {
    708         unsignedSize = constant->getUConst(0);
    709         size = static_cast<int>(unsignedSize);
    710     }
    711     else
    712     {
    713         size = constant->getIConst(0);
    714 
    715         if (size < 0)
    716         {
    717             error(line, "array size must be non-negative", "");
    718             size = 1;
    719             return true;
    720         }
    721 
    722         unsignedSize = static_cast<unsigned int>(size);
    723     }
    724 
    725     if (size == 0)
    726     {
    727         error(line, "array size must be greater than zero", "");
    728         size = 1;
    729         return true;
    730     }
    731 
    732     // The size of arrays is restricted here to prevent issues further down the
    733     // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
    734     // 4096 registers so this should be reasonable even for aggressively optimizable code.
    735     const unsigned int sizeLimit = 65536;
    736 
    737     if (unsignedSize > sizeLimit)
    738     {
    739         error(line, "array size too large", "");
    740         size = 1;
    741         return true;
    742     }
    743 
    744     return false;
    745 }
    746 
    747 //
    748 // See if this qualifier can be an array.
    749 //
    750 // Returns true if there is an error.
    751 //
    752 bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
    753 {
    754     if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConst)) {
    755         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
    756         return true;
    757     }
    758 
    759     return false;
    760 }
    761 
    762 //
    763 // See if this type can be an array.
    764 //
    765 // Returns true if there is an error.
    766 //
    767 bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
    768 {
    769     //
    770     // Can the type be an array?
    771     //
    772     if (type.array) {
    773         error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
    774         return true;
    775     }
    776 
    777     return false;
    778 }
    779 
    780 //
    781 // Do all the semantic checking for declaring an array, with and
    782 // without a size, and make the right changes to the symbol table.
    783 //
    784 // size == 0 means no specified size.
    785 //
    786 // Returns true if there was an error.
    787 //
    788 bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType &type, TVariable*& variable)
    789 {
    790     //
    791     // Don't check for reserved word use until after we know it's not in the symbol table,
    792     // because reserved arrays can be redeclared.
    793     //
    794 
    795     bool builtIn = false;
    796     bool sameScope = false;
    797     TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope);
    798     if (symbol == 0 || !sameScope) {
    799         if (reservedErrorCheck(line, identifier))
    800             return true;
    801 
    802         variable = new TVariable(&identifier, TType(type));
    803 
    804         if (type.arraySize)
    805             variable->getType().setArraySize(type.arraySize);
    806 
    807         if (! symbolTable.declare(*variable)) {
    808             delete variable;
    809             error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
    810             return true;
    811         }
    812     } else {
    813         if (! symbol->isVariable()) {
    814             error(line, "variable expected", identifier.c_str());
    815             return true;
    816         }
    817 
    818         variable = static_cast<TVariable*>(symbol);
    819         if (! variable->getType().isArray()) {
    820             error(line, "redeclaring non-array as array", identifier.c_str());
    821             return true;
    822         }
    823         if (variable->getType().getArraySize() > 0) {
    824             error(line, "redeclaration of array with size", identifier.c_str());
    825             return true;
    826         }
    827 
    828         if (! variable->getType().sameElementType(TType(type))) {
    829             error(line, "redeclaration of array with a different type", identifier.c_str());
    830             return true;
    831         }
    832 
    833         if (type.arraySize)
    834             variable->getType().setArraySize(type.arraySize);
    835     }
    836 
    837     if (voidErrorCheck(line, identifier, type))
    838         return true;
    839 
    840     return false;
    841 }
    842 
    843 //
    844 // Enforce non-initializer type/qualifier rules.
    845 //
    846 // Returns true if there was an error.
    847 //
    848 bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, const TString& identifier, TPublicType& type, bool array)
    849 {
    850     if (type.qualifier == EvqConst)
    851     {
    852         // Make the qualifier make sense.
    853         type.qualifier = EvqTemporary;
    854 
    855         if (array)
    856         {
    857             error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
    858         }
    859         else if (type.isStructureContainingArrays())
    860         {
    861             error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
    862         }
    863         else
    864         {
    865             error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
    866         }
    867 
    868         return true;
    869     }
    870 
    871     return false;
    872 }
    873 
    874 //
    875 // Do semantic checking for a variable declaration that has no initializer,
    876 // and update the symbol table.
    877 //
    878 // Returns true if there was an error.
    879 //
    880 bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& type, TVariable*& variable)
    881 {
    882     if (reservedErrorCheck(line, identifier))
    883         recover();
    884 
    885     variable = new TVariable(&identifier, TType(type));
    886 
    887     if (! symbolTable.declare(*variable)) {
    888         error(line, "redefinition", variable->getName().c_str());
    889         delete variable;
    890         variable = 0;
    891         return true;
    892     }
    893 
    894     if (voidErrorCheck(line, identifier, type))
    895         return true;
    896 
    897     return false;
    898 }
    899 
    900 bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
    901 {
    902     if (qualifier != EvqConst && qualifier != EvqTemporary) {
    903         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
    904         return true;
    905     }
    906     if (qualifier == EvqConst && paramQualifier != EvqIn) {
    907         error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
    908         return true;
    909     }
    910 
    911     if (qualifier == EvqConst)
    912         type->setQualifier(EvqConstReadOnly);
    913     else
    914         type->setQualifier(paramQualifier);
    915 
    916     return false;
    917 }
    918 
    919 bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
    920 {
    921     const TExtensionBehavior& extBehavior = extensionBehavior();
    922     TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
    923     if (iter == extBehavior.end()) {
    924         error(line, "extension", extension.c_str(), "is not supported");
    925         return true;
    926     }
    927     // In GLSL ES, an extension's default behavior is "disable".
    928     if (iter->second == EBhDisable || iter->second == EBhUndefined) {
    929         error(line, "extension", extension.c_str(), "is disabled");
    930         return true;
    931     }
    932     if (iter->second == EBhWarn) {
    933         warning(line, "extension", extension.c_str(), "is being used");
    934         return false;
    935     }
    936 
    937     return false;
    938 }
    939 
    940 bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier)
    941 {
    942     if (structQualifierErrorCheck(identifierLocation, publicType))
    943         return true;
    944 
    945     // check for layout qualifier issues
    946     const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
    947 
    948     if (layoutQualifier.matrixPacking != EmpUnspecified)
    949     {
    950         error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking), "only valid for interface blocks");
    951         return true;
    952     }
    953 
    954     if (layoutQualifier.blockStorage != EbsUnspecified)
    955     {
    956         error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage), "only valid for interface blocks");
    957         return true;
    958     }
    959 
    960     if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
    961     {
    962         return true;
    963     }
    964 
    965     return false;
    966 }
    967 
    968 bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier)
    969 {
    970     if (layoutQualifier.location != -1)
    971     {
    972         error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");
    973         return true;
    974     }
    975 
    976     return false;
    977 }
    978 
    979 bool TParseContext::supportsExtension(const char* extension)
    980 {
    981     const TExtensionBehavior& extbehavior = extensionBehavior();
    982     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
    983     return (iter != extbehavior.end());
    984 }
    985 
    986 bool TParseContext::isExtensionEnabled(const char* extension) const
    987 {
    988     const TExtensionBehavior& extbehavior = extensionBehavior();
    989     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
    990 
    991     if (iter == extbehavior.end())
    992     {
    993         return false;
    994     }
    995 
    996     return (iter->second == EBhEnable || iter->second == EBhRequire);
    997 }
    998 
    999 void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior)
   1000 {
   1001     pp::SourceLocation srcLoc;
   1002     srcLoc.file = loc.first_file;
   1003     srcLoc.line = loc.first_line;
   1004     directiveHandler.handleExtension(srcLoc, extName, behavior);
   1005 }
   1006 
   1007 void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value)
   1008 {
   1009     pp::SourceLocation srcLoc;
   1010     srcLoc.file = loc.first_file;
   1011     srcLoc.line = loc.first_line;
   1012     directiveHandler.handlePragma(srcLoc, name, value);
   1013 }
   1014 
   1015 /////////////////////////////////////////////////////////////////////////////////
   1016 //
   1017 // Non-Errors.
   1018 //
   1019 /////////////////////////////////////////////////////////////////////////////////
   1020 
   1021 //
   1022 // Look up a function name in the symbol table, and make sure it is a function.
   1023 //
   1024 // Return the function symbol if found, otherwise 0.
   1025 //
   1026 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn)
   1027 {
   1028     // First find by unmangled name to check whether the function name has been
   1029     // hidden by a variable name or struct typename.
   1030     // If a function is found, check for one with a matching argument list.
   1031     const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn);
   1032     if (symbol == 0 || symbol->isFunction()) {
   1033         symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
   1034     }
   1035 
   1036     if (symbol == 0) {
   1037         error(line, "no matching overloaded function found", call->getName().c_str());
   1038         return 0;
   1039     }
   1040 
   1041     if (!symbol->isFunction()) {
   1042         error(line, "function name expected", call->getName().c_str());
   1043         return 0;
   1044     }
   1045 
   1046     return static_cast<const TFunction*>(symbol);
   1047 }
   1048 
   1049 //
   1050 // Initializers show up in several places in the grammar.  Have one set of
   1051 // code to handle them here.
   1052 //
   1053 bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType,
   1054                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
   1055 {
   1056     TType type = TType(pType);
   1057 
   1058     if (variable == 0) {
   1059         if (reservedErrorCheck(line, identifier))
   1060             return true;
   1061 
   1062         if (voidErrorCheck(line, identifier, pType))
   1063             return true;
   1064 
   1065         //
   1066         // add variable to symbol table
   1067         //
   1068         variable = new TVariable(&identifier, type);
   1069         if (! symbolTable.declare(*variable)) {
   1070             error(line, "redefinition", variable->getName().c_str());
   1071             return true;
   1072             // don't delete variable, it's used by error recovery, and the pool
   1073             // pop will take care of the memory
   1074         }
   1075     }
   1076 
   1077     //
   1078     // identifier must be of type constant, a global, or a temporary
   1079     //
   1080     TQualifier qualifier = variable->getType().getQualifier();
   1081     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
   1082         error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
   1083         return true;
   1084     }
   1085     //
   1086     // test for and propagate constant
   1087     //
   1088 
   1089     if (qualifier == EvqConst) {
   1090         if (qualifier != initializer->getType().getQualifier()) {
   1091             std::stringstream extraInfoStream;
   1092             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
   1093             std::string extraInfo = extraInfoStream.str();
   1094             error(line, " assigning non-constant to", "=", extraInfo.c_str());
   1095             variable->getType().setQualifier(EvqTemporary);
   1096             return true;
   1097         }
   1098         if (type != initializer->getType()) {
   1099             error(line, " non-matching types for const initializer ",
   1100                 variable->getType().getQualifierString());
   1101             variable->getType().setQualifier(EvqTemporary);
   1102             return true;
   1103         }
   1104         if (initializer->getAsConstantUnion()) {
   1105             variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
   1106         } else if (initializer->getAsSymbolNode()) {
   1107             const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0);
   1108             const TVariable* tVar = static_cast<const TVariable*>(symbol);
   1109 
   1110             ConstantUnion* constArray = tVar->getConstPointer();
   1111             variable->shareConstPointer(constArray);
   1112         } else {
   1113             std::stringstream extraInfoStream;
   1114             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
   1115             std::string extraInfo = extraInfoStream.str();
   1116             error(line, " cannot assign to", "=", extraInfo.c_str());
   1117             variable->getType().setQualifier(EvqTemporary);
   1118             return true;
   1119         }
   1120     }
   1121 
   1122     if (qualifier != EvqConst) {
   1123         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
   1124         intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
   1125         if (intermNode == 0) {
   1126             assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
   1127             return true;
   1128         }
   1129     } else
   1130         intermNode = 0;
   1131 
   1132     return false;
   1133 }
   1134 
   1135 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
   1136 {
   1137     ASSERT(aggrNode != NULL);
   1138     if (!aggrNode->isConstructor())
   1139         return false;
   1140 
   1141     bool allConstant = true;
   1142 
   1143     // check if all the child nodes are constants so that they can be inserted into
   1144     // the parent node
   1145     TIntermSequence &sequence = aggrNode->getSequence() ;
   1146     for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
   1147         if (!(*p)->getAsTyped()->getAsConstantUnion())
   1148             return false;
   1149     }
   1150 
   1151     return allConstant;
   1152 }
   1153 
   1154 TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier)
   1155 {
   1156     TPublicType returnType = typeSpecifier;
   1157     returnType.qualifier = qualifier;
   1158     returnType.layoutQualifier = layoutQualifier;
   1159 
   1160     if (typeSpecifier.array)
   1161     {
   1162         error(typeSpecifier.line, "not supported", "first-class array");
   1163         recover();
   1164         returnType.setArray(false);
   1165     }
   1166 
   1167     if (shaderVersion < 300)
   1168     {
   1169         if (qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
   1170         {
   1171             error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
   1172             recover();
   1173         }
   1174 
   1175         if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
   1176             (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
   1177         {
   1178             error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
   1179             recover();
   1180         }
   1181     }
   1182     else
   1183     {
   1184         switch (qualifier)
   1185         {
   1186           case EvqSmoothIn:
   1187           case EvqSmoothOut:
   1188           case EvqVertexOut:
   1189           case EvqFragmentIn:
   1190           case EvqCentroidOut:
   1191           case EvqCentroidIn:
   1192             if (typeSpecifier.type == EbtBool)
   1193             {
   1194                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
   1195                 recover();
   1196             }
   1197             if (typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt)
   1198             {
   1199                 error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier));
   1200                 recover();
   1201             }
   1202             break;
   1203 
   1204           case EvqVertexIn:
   1205           case EvqFragmentOut:
   1206           case EvqFlatIn:
   1207           case EvqFlatOut:
   1208             if (typeSpecifier.type == EbtBool)
   1209             {
   1210                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
   1211                 recover();
   1212             }
   1213             break;
   1214 
   1215           default: break;
   1216         }
   1217     }
   1218 
   1219     return returnType;
   1220 }
   1221 
   1222 TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier)
   1223 {
   1224     TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
   1225     TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
   1226 
   1227     if (identifier != "")
   1228     {
   1229         if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
   1230             recover();
   1231 
   1232         // this error check can mutate the type
   1233         if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false))
   1234             recover();
   1235 
   1236         TVariable* variable = 0;
   1237 
   1238         if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable))
   1239             recover();
   1240 
   1241         if (variable && symbol)
   1242         {
   1243             symbol->setId(variable->getUniqueId());
   1244         }
   1245     }
   1246 
   1247     return aggregate;
   1248 }
   1249 
   1250 TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression)
   1251 {
   1252     if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
   1253         recover();
   1254 
   1255     // this error check can mutate the type
   1256     if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true))
   1257         recover();
   1258 
   1259     if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
   1260     {
   1261         recover();
   1262     }
   1263 
   1264     TPublicType arrayType = publicType;
   1265 
   1266     int size;
   1267     if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
   1268     {
   1269         recover();
   1270     }
   1271     else
   1272     {
   1273         arrayType.setArray(true, size);
   1274     }
   1275 
   1276     TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation);
   1277     TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
   1278     TVariable* variable = 0;
   1279 
   1280     if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable))
   1281         recover();
   1282 
   1283     if (variable && symbol)
   1284     {
   1285         symbol->setId(variable->getUniqueId());
   1286     }
   1287 
   1288     return aggregate;
   1289 }
   1290 
   1291 TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer)
   1292 {
   1293     if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier))
   1294         recover();
   1295 
   1296     TIntermNode* intermNode;
   1297     if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
   1298     {
   1299         //
   1300         // Build intermediate representation
   1301         //
   1302         return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL;
   1303     }
   1304     else
   1305     {
   1306         recover();
   1307         return NULL;
   1308     }
   1309 }
   1310 
   1311 TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier)
   1312 {
   1313     if (publicType.type == EbtInvariant && !identifierSymbol)
   1314     {
   1315         error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str());
   1316         recover();
   1317     }
   1318 
   1319     TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
   1320     TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
   1321 
   1322     if (structQualifierErrorCheck(identifierLocation, publicType))
   1323         recover();
   1324 
   1325     if (locationDeclaratorListCheck(identifierLocation, publicType))
   1326         recover();
   1327 
   1328     if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false))
   1329         recover();
   1330 
   1331     TVariable* variable = 0;
   1332     if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable))
   1333         recover();
   1334     if (symbol && variable)
   1335         symbol->setId(variable->getUniqueId());
   1336 
   1337     return intermAggregate;
   1338 }
   1339 
   1340 TIntermAggregate* TParseContext::parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression)
   1341 {
   1342     if (structQualifierErrorCheck(identifierLocation, publicType))
   1343         recover();
   1344 
   1345     if (locationDeclaratorListCheck(identifierLocation, publicType))
   1346         recover();
   1347 
   1348     if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true))
   1349         recover();
   1350 
   1351     if (arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
   1352     {
   1353         recover();
   1354     }
   1355     else if (indexExpression)
   1356     {
   1357         int size;
   1358         if (arraySizeErrorCheck(arrayLocation, indexExpression, size))
   1359             recover();
   1360         TPublicType arrayType(publicType);
   1361         arrayType.setArray(true, size);
   1362         TVariable* variable = NULL;
   1363         if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable))
   1364             recover();
   1365         TType type = TType(arrayType);
   1366         type.setArraySize(size);
   1367 
   1368         return intermediate.growAggregate(declaratorList, intermediate.addSymbol(variable ? variable->getUniqueId() : 0, identifier, type, identifierLocation), identifierLocation);
   1369     }
   1370     else
   1371     {
   1372         TPublicType arrayType(publicType);
   1373         arrayType.setArray(true);
   1374         TVariable* variable = NULL;
   1375         if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable))
   1376             recover();
   1377     }
   1378 
   1379     return NULL;
   1380 }
   1381 
   1382 TIntermAggregate* TParseContext::parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer)
   1383 {
   1384     if (structQualifierErrorCheck(identifierLocation, publicType))
   1385         recover();
   1386 
   1387     if (locationDeclaratorListCheck(identifierLocation, publicType))
   1388         recover();
   1389 
   1390     TIntermNode* intermNode;
   1391     if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
   1392     {
   1393         //
   1394         // build the intermediate representation
   1395         //
   1396         if (intermNode)
   1397         {
   1398             return intermediate.growAggregate(declaratorList, intermNode, initLocation);
   1399         }
   1400         else
   1401         {
   1402             return declaratorList;
   1403         }
   1404     }
   1405     else
   1406     {
   1407         recover();
   1408         return NULL;
   1409     }
   1410 }
   1411 
   1412 void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
   1413 {
   1414     if (typeQualifier.qualifier != EvqUniform)
   1415     {
   1416         error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
   1417         recover();
   1418         return;
   1419     }
   1420 
   1421     const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
   1422     ASSERT(!layoutQualifier.isEmpty());
   1423 
   1424     if (shaderVersion < 300)
   1425     {
   1426         error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
   1427         recover();
   1428         return;
   1429     }
   1430 
   1431     if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
   1432     {
   1433         recover();
   1434         return;
   1435     }
   1436 
   1437     if (layoutQualifier.matrixPacking != EmpUnspecified)
   1438     {
   1439         defaultMatrixPacking = layoutQualifier.matrixPacking;
   1440     }
   1441 
   1442     if (layoutQualifier.blockStorage != EbsUnspecified)
   1443     {
   1444         defaultBlockStorage = layoutQualifier.blockStorage;
   1445     }
   1446 }
   1447 
   1448 TFunction *TParseContext::addConstructorFunc(TPublicType publicType)
   1449 {
   1450     TOperator op = EOpNull;
   1451     if (publicType.userDef)
   1452     {
   1453         op = EOpConstructStruct;
   1454     }
   1455     else
   1456     {
   1457         switch (publicType.type)
   1458         {
   1459           case EbtFloat:
   1460             if (publicType.isMatrix())
   1461             {
   1462                 // TODO: non-square matrices
   1463                 switch(publicType.getCols())
   1464                 {
   1465                   case 2: op = EOpConstructMat2;  break;
   1466                   case 3: op = EOpConstructMat3;  break;
   1467                   case 4: op = EOpConstructMat4;  break;
   1468                 }
   1469             }
   1470             else
   1471             {
   1472                 switch(publicType.getNominalSize())
   1473                 {
   1474                   case 1: op = EOpConstructFloat; break;
   1475                   case 2: op = EOpConstructVec2;  break;
   1476                   case 3: op = EOpConstructVec3;  break;
   1477                   case 4: op = EOpConstructVec4;  break;
   1478                 }
   1479             }
   1480             break;
   1481 
   1482           case EbtInt:
   1483             switch(publicType.getNominalSize())
   1484             {
   1485               case 1: op = EOpConstructInt;   break;
   1486               case 2: op = EOpConstructIVec2; break;
   1487               case 3: op = EOpConstructIVec3; break;
   1488               case 4: op = EOpConstructIVec4; break;
   1489             }
   1490             break;
   1491 
   1492           case EbtUInt:
   1493             switch(publicType.getNominalSize())
   1494             {
   1495               case 1: op = EOpConstructUInt;  break;
   1496               case 2: op = EOpConstructUVec2; break;
   1497               case 3: op = EOpConstructUVec3; break;
   1498               case 4: op = EOpConstructUVec4; break;
   1499             }
   1500             break;
   1501 
   1502           case EbtBool:
   1503             switch(publicType.getNominalSize())
   1504             {
   1505                 case 1: op = EOpConstructBool;  break;
   1506                 case 2: op = EOpConstructBVec2; break;
   1507                 case 3: op = EOpConstructBVec3; break;
   1508                 case 4: op = EOpConstructBVec4; break;
   1509             }
   1510             break;
   1511 
   1512           default: break;
   1513         }
   1514 
   1515         if (op == EOpNull)
   1516         {
   1517             error(publicType.line, "cannot construct this type", getBasicString(publicType.type));
   1518             recover();
   1519             publicType.type = EbtFloat;
   1520             op = EOpConstructFloat;
   1521         }
   1522     }
   1523 
   1524     TString tempString;
   1525     TType type(publicType);
   1526     return new TFunction(&tempString, type, op);
   1527 }
   1528 
   1529 // This function is used to test for the correctness of the parameters passed to various constructor functions
   1530 // and also convert them to the right datatype if it is allowed and required.
   1531 //
   1532 // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
   1533 //
   1534 TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
   1535 {
   1536     if (node == 0)
   1537         return 0;
   1538 
   1539     TIntermAggregate* aggrNode = node->getAsAggregate();
   1540 
   1541     TFieldList::const_iterator memberTypes;
   1542     if (op == EOpConstructStruct)
   1543         memberTypes = type->getStruct()->fields().begin();
   1544 
   1545     TType elementType = *type;
   1546     if (type->isArray())
   1547         elementType.clearArrayness();
   1548 
   1549     bool singleArg;
   1550     if (aggrNode) {
   1551         if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
   1552             singleArg = true;
   1553         else
   1554             singleArg = false;
   1555     } else
   1556         singleArg = true;
   1557 
   1558     TIntermTyped *newNode;
   1559     if (singleArg) {
   1560         // If structure constructor or array constructor is being called
   1561         // for only one parameter inside the structure, we need to call constructStruct function once.
   1562         if (type->isArray())
   1563             newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
   1564         else if (op == EOpConstructStruct)
   1565             newNode = constructStruct(node, (*memberTypes)->type(), 1, node->getLine(), false);
   1566         else
   1567             newNode = constructBuiltIn(type, op, node, node->getLine(), false);
   1568 
   1569         if (newNode && newNode->getAsAggregate()) {
   1570             TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
   1571             if (constConstructor)
   1572                 return constConstructor;
   1573         }
   1574 
   1575         return newNode;
   1576     }
   1577 
   1578     //
   1579     // Handle list of arguments.
   1580     //
   1581     TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
   1582     // if the structure constructor contains more than one parameter, then construct
   1583     // each parameter
   1584 
   1585     int paramCount = 0;  // keeps a track of the constructor parameter number being checked
   1586 
   1587     // for each parameter to the constructor call, check to see if the right type is passed or convert them
   1588     // to the right type if possible (and allowed).
   1589     // for structure constructors, just check if the right type is passed, no conversion is allowed.
   1590 
   1591     for (TIntermSequence::iterator p = sequenceVector.begin();
   1592                                    p != sequenceVector.end(); p++, paramCount++) {
   1593         if (type->isArray())
   1594             newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
   1595         else if (op == EOpConstructStruct)
   1596             newNode = constructStruct(*p, (memberTypes[paramCount])->type(), paramCount+1, node->getLine(), true);
   1597         else
   1598             newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
   1599 
   1600         if (newNode) {
   1601             *p = newNode;
   1602         }
   1603     }
   1604 
   1605     TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
   1606     TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
   1607     if (constConstructor)
   1608         return constConstructor;
   1609 
   1610     return constructor;
   1611 }
   1612 
   1613 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
   1614 {
   1615     bool canBeFolded = areAllChildConst(aggrNode);
   1616     aggrNode->setType(type);
   1617     if (canBeFolded) {
   1618         bool returnVal = false;
   1619         ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
   1620         if (aggrNode->getSequence().size() == 1)  {
   1621             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
   1622         }
   1623         else {
   1624             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
   1625         }
   1626         if (returnVal)
   1627             return 0;
   1628 
   1629         return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
   1630     }
   1631 
   1632     return 0;
   1633 }
   1634 
   1635 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
   1636 // for the parameter to the constructor (passed to this function). Essentially, it converts
   1637 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
   1638 // float, then float is converted to int.
   1639 //
   1640 // Returns 0 for an error or the constructed node.
   1641 //
   1642 TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
   1643 {
   1644     TIntermTyped* newNode;
   1645     TOperator basicOp;
   1646 
   1647     //
   1648     // First, convert types as needed.
   1649     //
   1650     switch (op) {
   1651     case EOpConstructVec2:
   1652     case EOpConstructVec3:
   1653     case EOpConstructVec4:
   1654     case EOpConstructMat2:
   1655     case EOpConstructMat3:
   1656     case EOpConstructMat4:
   1657     case EOpConstructFloat:
   1658         basicOp = EOpConstructFloat;
   1659         break;
   1660 
   1661     case EOpConstructIVec2:
   1662     case EOpConstructIVec3:
   1663     case EOpConstructIVec4:
   1664     case EOpConstructInt:
   1665         basicOp = EOpConstructInt;
   1666         break;
   1667 
   1668     case EOpConstructUVec2:
   1669     case EOpConstructUVec3:
   1670     case EOpConstructUVec4:
   1671     case EOpConstructUInt:
   1672         basicOp = EOpConstructUInt;
   1673         break;
   1674 
   1675     case EOpConstructBVec2:
   1676     case EOpConstructBVec3:
   1677     case EOpConstructBVec4:
   1678     case EOpConstructBool:
   1679         basicOp = EOpConstructBool;
   1680         break;
   1681 
   1682     default:
   1683         error(line, "unsupported construction", "");
   1684         recover();
   1685 
   1686         return 0;
   1687     }
   1688     newNode = intermediate.addUnaryMath(basicOp, node, node->getLine());
   1689     if (newNode == 0) {
   1690         error(line, "can't convert", "constructor");
   1691         return 0;
   1692     }
   1693 
   1694     //
   1695     // Now, if there still isn't an operation to do the construction, and we need one, add one.
   1696     //
   1697 
   1698     // Otherwise, skip out early.
   1699     if (subset || (newNode != node && newNode->getType() == *type))
   1700         return newNode;
   1701 
   1702     // setAggregateOperator will insert a new node for the constructor, as needed.
   1703     return intermediate.setAggregateOperator(newNode, op, line);
   1704 }
   1705 
   1706 // This function tests for the type of the parameters to the structures constructors. Raises
   1707 // an error message if the expected type does not match the parameter passed to the constructor.
   1708 //
   1709 // Returns 0 for an error or the input node itself if the expected and the given parameter types match.
   1710 //
   1711 TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
   1712 {
   1713     if (*type == node->getAsTyped()->getType()) {
   1714         if (subset)
   1715             return node->getAsTyped();
   1716         else
   1717             return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
   1718     } else {
   1719         std::stringstream extraInfoStream;
   1720         extraInfoStream << "cannot convert parameter " << paramCount
   1721                         << " from '" << node->getAsTyped()->getType().getBasicString()
   1722                         << "' to '" << type->getBasicString() << "'";
   1723         std::string extraInfo = extraInfoStream.str();
   1724         error(line, "", "constructor", extraInfo.c_str());
   1725         recover();
   1726     }
   1727 
   1728     return 0;
   1729 }
   1730 
   1731 //
   1732 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
   1733 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
   1734 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
   1735 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
   1736 // a constant matrix.
   1737 //
   1738 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
   1739 {
   1740     TIntermTyped* typedNode;
   1741     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1742 
   1743     ConstantUnion *unionArray;
   1744     if (tempConstantNode) {
   1745         unionArray = tempConstantNode->getUnionArrayPointer();
   1746 
   1747         if (!unionArray) {
   1748             return node;
   1749         }
   1750     } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
   1751         error(line, "Cannot offset into the vector", "Error");
   1752         recover();
   1753 
   1754         return 0;
   1755     }
   1756 
   1757     ConstantUnion* constArray = new ConstantUnion[fields.num];
   1758 
   1759     for (int i = 0; i < fields.num; i++) {
   1760         if (fields.offsets[i] >= node->getType().getNominalSize()) {
   1761             std::stringstream extraInfoStream;
   1762             extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
   1763             std::string extraInfo = extraInfoStream.str();
   1764             error(line, "", "[", extraInfo.c_str());
   1765             recover();
   1766             fields.offsets[i] = 0;
   1767         }
   1768 
   1769         constArray[i] = unionArray[fields.offsets[i]];
   1770 
   1771     }
   1772     typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
   1773     return typedNode;
   1774 }
   1775 
   1776 //
   1777 // This function returns the column being accessed from a constant matrix. The values are retrieved from
   1778 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
   1779 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
   1780 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
   1781 //
   1782 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
   1783 {
   1784     TIntermTyped* typedNode;
   1785     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1786 
   1787     if (index >= node->getType().getCols()) {
   1788         std::stringstream extraInfoStream;
   1789         extraInfoStream << "matrix field selection out of range '" << index << "'";
   1790         std::string extraInfo = extraInfoStream.str();
   1791         error(line, "", "[", extraInfo.c_str());
   1792         recover();
   1793         index = 0;
   1794     }
   1795 
   1796     if (tempConstantNode) {
   1797          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
   1798          int size = tempConstantNode->getType().getCols();
   1799          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
   1800     } else {
   1801         error(line, "Cannot offset into the matrix", "Error");
   1802         recover();
   1803 
   1804         return 0;
   1805     }
   1806 
   1807     return typedNode;
   1808 }
   1809 
   1810 
   1811 //
   1812 // This function returns an element of an array accessed from a constant array. The values are retrieved from
   1813 // the symbol table and parse-tree is built for the type of the element. The input
   1814 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
   1815 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
   1816 //
   1817 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
   1818 {
   1819     TIntermTyped* typedNode;
   1820     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1821     TType arrayElementType = node->getType();
   1822     arrayElementType.clearArrayness();
   1823 
   1824     if (index >= node->getType().getArraySize()) {
   1825         std::stringstream extraInfoStream;
   1826         extraInfoStream << "array field selection out of range '" << index << "'";
   1827         std::string extraInfo = extraInfoStream.str();
   1828         error(line, "", "[", extraInfo.c_str());
   1829         recover();
   1830         index = 0;
   1831     }
   1832 
   1833     if (tempConstantNode) {
   1834         size_t arrayElementSize = arrayElementType.getObjectSize();
   1835         ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
   1836         typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
   1837     } else {
   1838         error(line, "Cannot offset into the array", "Error");
   1839         recover();
   1840 
   1841         return 0;
   1842     }
   1843 
   1844     return typedNode;
   1845 }
   1846 
   1847 
   1848 //
   1849 // This function returns the value of a particular field inside a constant structure from the symbol table.
   1850 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
   1851 // function and returns the parse-tree with the values of the embedded/nested struct.
   1852 //
   1853 TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line)
   1854 {
   1855     const TFieldList& fields = node->getType().getStruct()->fields();
   1856     size_t instanceSize = 0;
   1857 
   1858     for (size_t index = 0; index < fields.size(); ++index) {
   1859         if (fields[index]->name() == identifier) {
   1860             break;
   1861         } else {
   1862             instanceSize += fields[index]->type()->getObjectSize();
   1863         }
   1864     }
   1865 
   1866     TIntermTyped *typedNode;
   1867     TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
   1868     if (tempConstantNode) {
   1869          ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
   1870 
   1871          typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
   1872     } else {
   1873         error(line, "Cannot offset into the structure", "Error");
   1874         recover();
   1875 
   1876         return 0;
   1877     }
   1878 
   1879     return typedNode;
   1880 }
   1881 
   1882 //
   1883 // Interface/uniform blocks
   1884 //
   1885 TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
   1886                                                    const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
   1887 {
   1888     if (reservedErrorCheck(nameLine, blockName))
   1889         recover();
   1890 
   1891     if (typeQualifier.qualifier != EvqUniform)
   1892     {
   1893         error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
   1894         recover();
   1895     }
   1896 
   1897     TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
   1898     if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
   1899     {
   1900         recover();
   1901     }
   1902 
   1903     if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
   1904     {
   1905         blockLayoutQualifier.matrixPacking = defaultMatrixPacking;
   1906     }
   1907 
   1908     if (blockLayoutQualifier.blockStorage == EbsUnspecified)
   1909     {
   1910         blockLayoutQualifier.blockStorage = defaultBlockStorage;
   1911     }
   1912 
   1913     TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName);
   1914     if (!symbolTable.declare(*blockNameSymbol)) {
   1915         error(nameLine, "redefinition", blockName.c_str(), "interface block name");
   1916         recover();
   1917     }
   1918 
   1919     // check for sampler types and apply layout qualifiers
   1920     for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
   1921         TField* field = (*fieldList)[memberIndex];
   1922         TType* fieldType = field->type();
   1923         if (IsSampler(fieldType->getBasicType())) {
   1924             error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
   1925             recover();
   1926         }
   1927 
   1928         const TQualifier qualifier = fieldType->getQualifier();
   1929         switch (qualifier)
   1930         {
   1931           case EvqGlobal:
   1932           case EvqUniform:
   1933             break;
   1934           default:
   1935             error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
   1936             recover();
   1937             break;
   1938         }
   1939 
   1940         // check layout qualifiers
   1941         TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
   1942         if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
   1943         {
   1944             recover();
   1945         }
   1946 
   1947         if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
   1948         {
   1949             error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
   1950             recover();
   1951         }
   1952 
   1953         if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
   1954         {
   1955             fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
   1956         }
   1957         else if (!fieldType->isMatrix())
   1958         {
   1959             error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types");
   1960             recover();
   1961         }
   1962 
   1963         fieldType->setLayoutQualifier(fieldLayoutQualifier);
   1964     }
   1965 
   1966     // add array index
   1967     int arraySize = 0;
   1968     if (arrayIndex != NULL)
   1969     {
   1970         if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
   1971             recover();
   1972     }
   1973 
   1974     TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
   1975     TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);
   1976 
   1977     TString symbolName = "";
   1978     int symbolId = 0;
   1979 
   1980     if (!instanceName)
   1981     {
   1982         // define symbols for the members of the interface block
   1983         for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
   1984         {
   1985             TField* field = (*fieldList)[memberIndex];
   1986             TType* fieldType = field->type();
   1987 
   1988             // set parent pointer of the field variable
   1989             fieldType->setInterfaceBlock(interfaceBlock);
   1990 
   1991             TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
   1992             fieldVariable->setQualifier(typeQualifier.qualifier);
   1993 
   1994             if (!symbolTable.declare(*fieldVariable)) {
   1995                 error(field->line(), "redefinition", field->name().c_str(), "interface block member name");
   1996                 recover();
   1997             }
   1998         }
   1999     }
   2000     else
   2001     {
   2002         // add a symbol for this interface block
   2003         TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
   2004         instanceTypeDef->setQualifier(typeQualifier.qualifier);
   2005 
   2006         if (!symbolTable.declare(*instanceTypeDef)) {
   2007             error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
   2008             recover();
   2009         }
   2010 
   2011         symbolId = instanceTypeDef->getUniqueId();
   2012         symbolName = instanceTypeDef->getName();
   2013     }
   2014 
   2015     TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
   2016     aggregate->setOp(EOpDeclaration);
   2017 
   2018     exitStructDeclaration();
   2019     return aggregate;
   2020 }
   2021 
   2022 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
   2023 {
   2024     ++structNestingLevel;
   2025 
   2026     // Embedded structure definitions are not supported per GLSL ES spec.
   2027     // They aren't allowed in GLSL either, but we need to detect this here
   2028     // so we don't rely on the GLSL compiler to catch it.
   2029     if (structNestingLevel > 1) {
   2030         error(line, "", "Embedded struct definitions are not allowed");
   2031         return true;
   2032     }
   2033 
   2034     return false;
   2035 }
   2036 
   2037 void TParseContext::exitStructDeclaration()
   2038 {
   2039     --structNestingLevel;
   2040 }
   2041 
   2042 namespace {
   2043 
   2044 const int kWebGLMaxStructNesting = 4;
   2045 
   2046 }  // namespace
   2047 
   2048 bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
   2049 {
   2050     if (!IsWebGLBasedSpec(shaderSpec)) {
   2051         return false;
   2052     }
   2053 
   2054     if (field.type()->getBasicType() != EbtStruct) {
   2055         return false;
   2056     }
   2057 
   2058     // We're already inside a structure definition at this point, so add
   2059     // one to the field's struct nesting.
   2060     if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
   2061         std::stringstream reasonStream;
   2062         reasonStream << "Reference of struct type "
   2063                      << field.type()->getStruct()->name().c_str()
   2064                      << " exceeds maximum allowed nesting level of "
   2065                      << kWebGLMaxStructNesting;
   2066         std::string reason = reasonStream.str();
   2067         error(line, reason.c_str(), field.name().c_str(), "");
   2068         return true;
   2069     }
   2070 
   2071     return false;
   2072 }
   2073 
   2074 //
   2075 // Parse an array index expression
   2076 //
   2077 TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
   2078 {
   2079     TIntermTyped *indexedExpression = NULL;
   2080 
   2081     if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
   2082     {
   2083         if (baseExpression->getAsSymbolNode())
   2084         {
   2085             error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
   2086         }
   2087         else
   2088         {
   2089             error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
   2090         }
   2091         recover();
   2092     }
   2093 
   2094     if (indexExpression->getQualifier() == EvqConst)
   2095     {
   2096         int index = indexExpression->getAsConstantUnion()->getIConst(0);
   2097         if (index < 0)
   2098         {
   2099             std::stringstream infoStream;
   2100             infoStream << index;
   2101             std::string info = infoStream.str();
   2102             error(location, "negative index", info.c_str());
   2103             recover();
   2104             index = 0;
   2105         }
   2106         if (baseExpression->getType().getQualifier() == EvqConst)
   2107         {
   2108             if (baseExpression->isArray())
   2109             {
   2110                 // constant folding for arrays
   2111                 indexedExpression = addConstArrayNode(index, baseExpression, location);
   2112             }
   2113             else if (baseExpression->isVector())
   2114             {
   2115                 // constant folding for vectors
   2116                 TVectorFields fields;
   2117                 fields.num = 1;
   2118                 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
   2119                 indexedExpression = addConstVectorNode(fields, baseExpression, location);
   2120             }
   2121             else if (baseExpression->isMatrix())
   2122             {
   2123                 // constant folding for matrices
   2124                 indexedExpression = addConstMatrixNode(index, baseExpression, location);
   2125             }
   2126         }
   2127         else
   2128         {
   2129             if (baseExpression->isArray())
   2130             {
   2131                 if (index >= baseExpression->getType().getArraySize())
   2132                 {
   2133                     std::stringstream extraInfoStream;
   2134                     extraInfoStream << "array index out of range '" << index << "'";
   2135                     std::string extraInfo = extraInfoStream.str();
   2136                     error(location, "", "[", extraInfo.c_str());
   2137                     recover();
   2138                     index = baseExpression->getType().getArraySize() - 1;
   2139                 }
   2140                 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
   2141                 {
   2142                     error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
   2143                     recover();
   2144                     index = 0;
   2145                 }
   2146             }
   2147             else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
   2148             {
   2149                 std::stringstream extraInfoStream;
   2150                 extraInfoStream << "field selection out of range '" << index << "'";
   2151                 std::string extraInfo = extraInfoStream.str();
   2152                 error(location, "", "[", extraInfo.c_str());
   2153                 recover();
   2154                 index = baseExpression->getType().getNominalSize() - 1;
   2155             }
   2156 
   2157             indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
   2158             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
   2159         }
   2160     }
   2161     else
   2162     {
   2163         if (baseExpression->isInterfaceBlock())
   2164         {
   2165             error(location, "", "[", "array indexes for interface blocks arrays must be constant integral expressions");
   2166             recover();
   2167         }
   2168         else if (baseExpression->getQualifier() == EvqFragmentOut)
   2169         {
   2170             error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
   2171             recover();
   2172         }
   2173 
   2174         indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
   2175     }
   2176 
   2177     if (indexedExpression == 0)
   2178     {
   2179         ConstantUnion *unionArray = new ConstantUnion[1];
   2180         unionArray->setFConst(0.0f);
   2181         indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
   2182     }
   2183     else if (baseExpression->isArray())
   2184     {
   2185         const TType &baseType = baseExpression->getType();
   2186         if (baseType.getStruct())
   2187         {
   2188             TType copyOfType(baseType.getStruct());
   2189             indexedExpression->setType(copyOfType);
   2190         }
   2191         else if (baseType.isInterfaceBlock())
   2192         {
   2193             TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0);
   2194             indexedExpression->setType(copyOfType);
   2195         }
   2196         else
   2197         {
   2198             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->getSecondarySize()));
   2199         }
   2200 
   2201         if (baseExpression->getType().getQualifier() == EvqConst)
   2202         {
   2203             indexedExpression->getTypePointer()->setQualifier(EvqConst);
   2204         }
   2205     }
   2206     else if (baseExpression->isMatrix())
   2207     {
   2208         TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
   2209         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getRows()));
   2210     }
   2211     else if (baseExpression->isVector())
   2212     {
   2213         TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
   2214         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
   2215     }
   2216     else
   2217     {
   2218         indexedExpression->setType(baseExpression->getType());
   2219     }
   2220 
   2221     return indexedExpression;
   2222 }
   2223 
   2224 TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation)
   2225 {
   2226     TIntermTyped *indexedExpression = NULL;
   2227 
   2228     if (baseExpression->isArray())
   2229     {
   2230         error(fieldLocation, "cannot apply dot operator to an array", ".");
   2231         recover();
   2232     }
   2233 
   2234     if (baseExpression->isVector())
   2235     {
   2236         TVectorFields fields;
   2237         if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
   2238         {
   2239             fields.num = 1;
   2240             fields.offsets[0] = 0;
   2241             recover();
   2242         }
   2243 
   2244         if (baseExpression->getType().getQualifier() == EvqConst)
   2245         {
   2246             // constant folding for vector fields
   2247             indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
   2248             if (indexedExpression == 0)
   2249             {
   2250                 recover();
   2251                 indexedExpression = baseExpression;
   2252             }
   2253             else
   2254             {
   2255                 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, (int) (fieldString).size()));
   2256             }
   2257         }
   2258         else
   2259         {
   2260             TString vectorString = fieldString;
   2261             TIntermTyped* index = intermediate.addSwizzle(fields, fieldLocation);
   2262             indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
   2263             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, (int) vectorString.size()));
   2264         }
   2265     }
   2266     else if (baseExpression->isMatrix())
   2267     {
   2268         TMatrixFields fields;
   2269         if (!parseMatrixFields(fieldString, baseExpression->getCols(), baseExpression->getRows(), fields, fieldLocation))
   2270         {
   2271             fields.wholeRow = false;
   2272             fields.wholeCol = false;
   2273             fields.row = 0;
   2274             fields.col = 0;
   2275             recover();
   2276         }
   2277 
   2278         if (fields.wholeRow || fields.wholeCol)
   2279         {
   2280             error(dotLocation, " non-scalar fields not implemented yet", ".");
   2281             recover();
   2282             ConstantUnion *unionArray = new ConstantUnion[1];
   2283             unionArray->setIConst(0);
   2284             TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation);
   2285             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
   2286             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getCols(), baseExpression->getRows()));
   2287         }
   2288         else
   2289         {
   2290             ConstantUnion *unionArray = new ConstantUnion[1];
   2291             unionArray->setIConst(fields.col * baseExpression->getRows() + fields.row);
   2292             TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation);
   2293             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
   2294             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision()));
   2295         }
   2296     }
   2297     else if (baseExpression->getBasicType() == EbtStruct)
   2298     {
   2299         bool fieldFound = false;
   2300         const TFieldList& fields = baseExpression->getType().getStruct()->fields();
   2301         if (fields.empty())
   2302         {
   2303             error(dotLocation, "structure has no fields", "Internal Error");
   2304             recover();
   2305             indexedExpression = baseExpression;
   2306         }
   2307         else
   2308         {
   2309             unsigned int i;
   2310             for (i = 0; i < fields.size(); ++i)
   2311             {
   2312                 if (fields[i]->name() == fieldString)
   2313                 {
   2314                     fieldFound = true;
   2315                     break;
   2316                 }
   2317             }
   2318             if (fieldFound)
   2319             {
   2320                 if (baseExpression->getType().getQualifier() == EvqConst)
   2321                 {
   2322                     indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
   2323                     if (indexedExpression == 0)
   2324                     {
   2325                         recover();
   2326                         indexedExpression = baseExpression;
   2327                     }
   2328                     else
   2329                     {
   2330                         indexedExpression->setType(*fields[i]->type());
   2331                         // change the qualifier of the return type, not of the structure field
   2332                         // as the structure definition is shared between various structures.
   2333                         indexedExpression->getTypePointer()->setQualifier(EvqConst);
   2334                     }
   2335                 }
   2336                 else
   2337                 {
   2338                     ConstantUnion *unionArray = new ConstantUnion[1];
   2339                     unionArray->setIConst(i);
   2340                     TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
   2341                     indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
   2342                     indexedExpression->setType(*fields[i]->type());
   2343                 }
   2344             }
   2345             else
   2346             {
   2347                 error(dotLocation, " no such field in structure", fieldString.c_str());
   2348                 recover();
   2349                 indexedExpression = baseExpression;
   2350             }
   2351         }
   2352     }
   2353     else if (baseExpression->isInterfaceBlock())
   2354     {
   2355         bool fieldFound = false;
   2356         const TFieldList& fields = baseExpression->getType().getInterfaceBlock()->fields();
   2357         if (fields.empty())
   2358         {
   2359             error(dotLocation, "interface block has no fields", "Internal Error");
   2360             recover();
   2361             indexedExpression = baseExpression;
   2362         }
   2363         else
   2364         {
   2365             unsigned int i;
   2366             for (i = 0; i < fields.size(); ++i)
   2367             {
   2368                 if (fields[i]->name() == fieldString)
   2369                 {
   2370                     fieldFound = true;
   2371                     break;
   2372                 }
   2373             }
   2374             if (fieldFound)
   2375             {
   2376                 ConstantUnion *unionArray = new ConstantUnion[1];
   2377                 unionArray->setIConst(i);
   2378                 TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
   2379                 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation);
   2380                 indexedExpression->setType(*fields[i]->type());
   2381             }
   2382             else
   2383             {
   2384                 error(dotLocation, " no such field in interface block", fieldString.c_str());
   2385                 recover();
   2386                 indexedExpression = baseExpression;
   2387             }
   2388         }
   2389     }
   2390     else
   2391     {
   2392         if (shaderVersion < 300)
   2393         {
   2394             error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str());
   2395         }
   2396         else
   2397         {
   2398             error(dotLocation, " field selection requires structure, vector, matrix, or interface block on left hand side", fieldString.c_str());
   2399         }
   2400         recover();
   2401         indexedExpression = baseExpression;
   2402     }
   2403 
   2404     return indexedExpression;
   2405 }
   2406 
   2407 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
   2408 {
   2409     TLayoutQualifier qualifier;
   2410 
   2411     qualifier.location = -1;
   2412     qualifier.matrixPacking = EmpUnspecified;
   2413     qualifier.blockStorage = EbsUnspecified;
   2414 
   2415     if (qualifierType == "shared")
   2416     {
   2417         qualifier.blockStorage = EbsShared;
   2418     }
   2419     else if (qualifierType == "packed")
   2420     {
   2421         qualifier.blockStorage = EbsPacked;
   2422     }
   2423     else if (qualifierType == "std140")
   2424     {
   2425         qualifier.blockStorage = EbsStd140;
   2426     }
   2427     else if (qualifierType == "row_major")
   2428     {
   2429         qualifier.matrixPacking = EmpRowMajor;
   2430     }
   2431     else if (qualifierType == "column_major")
   2432     {
   2433         qualifier.matrixPacking = EmpColumnMajor;
   2434     }
   2435     else if (qualifierType == "location")
   2436     {
   2437         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
   2438         recover();
   2439     }
   2440     else
   2441     {
   2442         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
   2443         recover();
   2444     }
   2445 
   2446     return qualifier;
   2447 }
   2448 
   2449 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
   2450 {
   2451     TLayoutQualifier qualifier;
   2452 
   2453     qualifier.location = -1;
   2454     qualifier.matrixPacking = EmpUnspecified;
   2455     qualifier.blockStorage = EbsUnspecified;
   2456 
   2457     if (qualifierType != "location")
   2458     {
   2459         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
   2460         recover();
   2461     }
   2462     else
   2463     {
   2464         // must check that location is non-negative
   2465         if (intValue < 0)
   2466         {
   2467             error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
   2468             recover();
   2469         }
   2470         else
   2471         {
   2472             qualifier.location = intValue;
   2473         }
   2474     }
   2475 
   2476     return qualifier;
   2477 }
   2478 
   2479 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
   2480 {
   2481     TLayoutQualifier joinedQualifier = leftQualifier;
   2482 
   2483     if (rightQualifier.location != -1)
   2484     {
   2485         joinedQualifier.location = rightQualifier.location;
   2486     }
   2487     if (rightQualifier.matrixPacking != EmpUnspecified)
   2488     {
   2489         joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
   2490     }
   2491     if (rightQualifier.blockStorage != EbsUnspecified)
   2492     {
   2493         joinedQualifier.blockStorage = rightQualifier.blockStorage;
   2494     }
   2495 
   2496     return joinedQualifier;
   2497 }
   2498 
   2499 TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
   2500                                                        const TSourceLoc &storageLoc, TQualifier storageQualifier)
   2501 {
   2502     TQualifier mergedQualifier = EvqSmoothIn;
   2503 
   2504     if (storageQualifier == EvqFragmentIn) {
   2505         if (interpolationQualifier == EvqSmooth)
   2506             mergedQualifier = EvqSmoothIn;
   2507         else if (interpolationQualifier == EvqFlat)
   2508             mergedQualifier = EvqFlatIn;
   2509         else UNREACHABLE();
   2510     }
   2511     else if (storageQualifier == EvqCentroidIn) {
   2512         if (interpolationQualifier == EvqSmooth)
   2513             mergedQualifier = EvqCentroidIn;
   2514         else if (interpolationQualifier == EvqFlat)
   2515             mergedQualifier = EvqFlatIn;
   2516         else UNREACHABLE();
   2517     }
   2518     else if (storageQualifier == EvqVertexOut) {
   2519         if (interpolationQualifier == EvqSmooth)
   2520             mergedQualifier = EvqSmoothOut;
   2521         else if (interpolationQualifier == EvqFlat)
   2522             mergedQualifier = EvqFlatOut;
   2523         else UNREACHABLE();
   2524     }
   2525     else if (storageQualifier == EvqCentroidOut) {
   2526         if (interpolationQualifier == EvqSmooth)
   2527             mergedQualifier = EvqCentroidOut;
   2528         else if (interpolationQualifier == EvqFlat)
   2529             mergedQualifier = EvqFlatOut;
   2530         else UNREACHABLE();
   2531     }
   2532     else {
   2533         error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString(interpolationQualifier));
   2534         recover();
   2535 
   2536         mergedQualifier = storageQualifier;
   2537     }
   2538 
   2539     TPublicType type;
   2540     type.setBasic(EbtVoid, mergedQualifier, storageLoc);
   2541     return type;
   2542 }
   2543 
   2544 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList)
   2545 {
   2546     if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier)) {
   2547         recover();
   2548     }
   2549 
   2550     for (unsigned int i = 0; i < fieldList->size(); ++i) {
   2551         //
   2552         // Careful not to replace already known aspects of type, like array-ness
   2553         //
   2554         TType* type = (*fieldList)[i]->type();
   2555         type->setBasicType(typeSpecifier.type);
   2556         type->setPrimarySize(typeSpecifier.primarySize);
   2557         type->setSecondarySize(typeSpecifier.secondarySize);
   2558         type->setPrecision(typeSpecifier.precision);
   2559         type->setQualifier(typeSpecifier.qualifier);
   2560         type->setLayoutQualifier(typeSpecifier.layoutQualifier);
   2561 
   2562         // don't allow arrays of arrays
   2563         if (type->isArray()) {
   2564             if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
   2565                 recover();
   2566         }
   2567         if (typeSpecifier.array)
   2568             type->setArraySize(typeSpecifier.arraySize);
   2569         if (typeSpecifier.userDef) {
   2570             type->setStruct(typeSpecifier.userDef->getStruct());
   2571         }
   2572 
   2573         if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i])) {
   2574             recover();
   2575         }
   2576     }
   2577 
   2578     return fieldList;
   2579 }
   2580 
   2581 TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList)
   2582 {
   2583     TStructure* structure = new TStructure(structName, fieldList);
   2584     TType* structureType = new TType(structure);
   2585 
   2586     structure->setUniqueId(TSymbolTable::nextUniqueId());
   2587 
   2588     if (!structName->empty())
   2589     {
   2590         if (reservedErrorCheck(nameLine, *structName))
   2591         {
   2592             recover();
   2593         }
   2594         TVariable* userTypeDef = new TVariable(structName, *structureType, true);
   2595         if (!symbolTable.declare(*userTypeDef)) {
   2596             error(nameLine, "redefinition", structName->c_str(), "struct");
   2597             recover();
   2598         }
   2599     }
   2600 
   2601     // ensure we do not specify any storage qualifiers on the struct members
   2602     for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
   2603     {
   2604         const TField &field = *(*fieldList)[typeListIndex];
   2605         const TQualifier qualifier = field.type()->getQualifier();
   2606         switch (qualifier)
   2607         {
   2608           case EvqGlobal:
   2609           case EvqTemporary:
   2610             break;
   2611           default:
   2612             error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
   2613             recover();
   2614             break;
   2615         }
   2616     }
   2617 
   2618     TPublicType publicType;
   2619     publicType.setBasic(EbtStruct, EvqTemporary, structLine);
   2620     publicType.userDef = structureType;
   2621     exitStructDeclaration();
   2622 
   2623     return publicType;
   2624 }
   2625 
   2626 //
   2627 // Parse an array of strings using yyparse.
   2628 //
   2629 // Returns 0 for success.
   2630 //
   2631 int PaParseStrings(size_t count, const char* const string[], const int length[],
   2632                    TParseContext* context) {
   2633     if ((count == 0) || (string == NULL))
   2634         return 1;
   2635 
   2636     if (glslang_initialize(context))
   2637         return 1;
   2638 
   2639     int error = glslang_scan(count, string, length, context);
   2640     if (!error)
   2641         error = glslang_parse(context);
   2642 
   2643     glslang_finalize(context);
   2644 
   2645     return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
   2646 }
   2647 
   2648 
   2649 
   2650