Home | History | Annotate | Download | only in compiler
      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/ParseHelper.h"
      8 
      9 #include <stdarg.h>
     10 #include <stdio.h>
     11 
     12 #include "compiler/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 matSize, 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 >= matSize || fields.col >= matSize) {
    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::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::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             return lValueErrorCheck(line, op, binaryNode->getLeft());
    281         case EOpVectorSwizzle:
    282             errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
    283             if (!errorReturn) {
    284                 int offset[4] = {0,0,0,0};
    285 
    286                 TIntermTyped* rightNode = binaryNode->getRight();
    287                 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
    288 
    289                 for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
    290                                                p != aggrNode->getSequence().end(); p++) {
    291                     int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
    292                     offset[value]++;
    293                     if (offset[value] > 1) {
    294                         error(line, " l-value of swizzle cannot have duplicate components", op);
    295 
    296                         return true;
    297                     }
    298                 }
    299             }
    300 
    301             return errorReturn;
    302         default:
    303             break;
    304         }
    305         error(line, " l-value required", op);
    306 
    307         return true;
    308     }
    309 
    310 
    311     const char* symbol = 0;
    312     if (symNode != 0)
    313         symbol = symNode->getSymbol().c_str();
    314 
    315     const char* message = 0;
    316     switch (node->getQualifier()) {
    317     case EvqConst:          message = "can't modify a const";        break;
    318     case EvqConstReadOnly:  message = "can't modify a const";        break;
    319     case EvqAttribute:      message = "can't modify an attribute";   break;
    320     case EvqUniform:        message = "can't modify a uniform";      break;
    321     case EvqVaryingIn:      message = "can't modify a varying";      break;
    322     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
    323     case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
    324     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
    325     default:
    326 
    327         //
    328         // Type that can't be written to?
    329         //
    330         switch (node->getBasicType()) {
    331         case EbtSampler2D:
    332         case EbtSamplerCube:
    333             message = "can't modify a sampler";
    334             break;
    335         case EbtVoid:
    336             message = "can't modify void";
    337             break;
    338         default:
    339             break;
    340         }
    341     }
    342 
    343     if (message == 0 && binaryNode == 0 && symNode == 0) {
    344         error(line, " l-value required", op);
    345 
    346         return true;
    347     }
    348 
    349 
    350     //
    351     // Everything else is okay, no error.
    352     //
    353     if (message == 0)
    354         return false;
    355 
    356     //
    357     // If we get here, we have an error and a message.
    358     //
    359     if (symNode) {
    360         std::stringstream extraInfoStream;
    361         extraInfoStream << "\"" << symbol << "\" (" << message << ")";
    362         std::string extraInfo = extraInfoStream.str();
    363         error(line, " l-value required", op, extraInfo.c_str());
    364     }
    365     else {
    366         std::stringstream extraInfoStream;
    367         extraInfoStream << "(" << message << ")";
    368         std::string extraInfo = extraInfoStream.str();
    369         error(line, " l-value required", op, extraInfo.c_str());
    370     }
    371 
    372     return true;
    373 }
    374 
    375 //
    376 // Both test, and if necessary spit out an error, to see if the node is really
    377 // a constant.
    378 //
    379 // Returns true if the was an error.
    380 //
    381 bool TParseContext::constErrorCheck(TIntermTyped* node)
    382 {
    383     if (node->getQualifier() == EvqConst)
    384         return false;
    385 
    386     error(node->getLine(), "constant expression required", "");
    387 
    388     return true;
    389 }
    390 
    391 //
    392 // Both test, and if necessary spit out an error, to see if the node is really
    393 // an integer.
    394 //
    395 // Returns true if the was an error.
    396 //
    397 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
    398 {
    399     if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
    400         return false;
    401 
    402     error(node->getLine(), "integer expression required", token);
    403 
    404     return true;
    405 }
    406 
    407 //
    408 // Both test, and if necessary spit out an error, to see if we are currently
    409 // globally scoped.
    410 //
    411 // Returns true if the was an error.
    412 //
    413 bool TParseContext::globalErrorCheck(const TSourceLoc& line, bool global, const char* token)
    414 {
    415     if (global)
    416         return false;
    417 
    418     error(line, "only allowed at global scope", token);
    419 
    420     return true;
    421 }
    422 
    423 //
    424 // For now, keep it simple:  if it starts "gl_", it's reserved, independent
    425 // of scope.  Except, if the symbol table is at the built-in push-level,
    426 // which is when we are parsing built-ins.
    427 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
    428 // webgl shader.
    429 //
    430 // Returns true if there was an error.
    431 //
    432 bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& identifier)
    433 {
    434     static const char* reservedErrMsg = "reserved built-in name";
    435     if (!symbolTable.atBuiltInLevel()) {
    436         if (identifier.compare(0, 3, "gl_") == 0) {
    437             error(line, reservedErrMsg, "gl_");
    438             return true;
    439         }
    440         if (isWebGLBasedSpec(shaderSpec)) {
    441             if (identifier.compare(0, 6, "webgl_") == 0) {
    442                 error(line, reservedErrMsg, "webgl_");
    443                 return true;
    444             }
    445             if (identifier.compare(0, 7, "_webgl_") == 0) {
    446                 error(line, reservedErrMsg, "_webgl_");
    447                 return true;
    448             }
    449             if (shaderSpec == SH_CSS_SHADERS_SPEC && identifier.compare(0, 4, "css_") == 0) {
    450                 error(line, reservedErrMsg, "css_");
    451                 return true;
    452             }
    453         }
    454         if (identifier.find("__") != TString::npos) {
    455             error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
    456             return true;
    457         }
    458     }
    459 
    460     return false;
    461 }
    462 
    463 //
    464 // Make sure there is enough data provided to the constructor to build
    465 // something of the type of the constructor.  Also returns the type of
    466 // the constructor.
    467 //
    468 // Returns true if there was an error in construction.
    469 //
    470 bool TParseContext::constructorErrorCheck(const TSourceLoc& line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
    471 {
    472     *type = function.getReturnType();
    473 
    474     bool constructingMatrix = false;
    475     switch(op) {
    476     case EOpConstructMat2:
    477     case EOpConstructMat3:
    478     case EOpConstructMat4:
    479         constructingMatrix = true;
    480         break;
    481     default:
    482         break;
    483     }
    484 
    485     //
    486     // Note: It's okay to have too many components available, but not okay to have unused
    487     // arguments.  'full' will go to true when enough args have been seen.  If we loop
    488     // again, there is an extra argument, so 'overfull' will become true.
    489     //
    490 
    491     size_t size = 0;
    492     bool constType = true;
    493     bool full = false;
    494     bool overFull = false;
    495     bool matrixInMatrix = false;
    496     bool arrayArg = false;
    497     for (size_t i = 0; i < function.getParamCount(); ++i) {
    498         const TParameter& param = function.getParam(i);
    499         size += param.type->getObjectSize();
    500 
    501         if (constructingMatrix && param.type->isMatrix())
    502             matrixInMatrix = true;
    503         if (full)
    504             overFull = true;
    505         if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
    506             full = true;
    507         if (param.type->getQualifier() != EvqConst)
    508             constType = false;
    509         if (param.type->isArray())
    510             arrayArg = true;
    511     }
    512 
    513     if (constType)
    514         type->setQualifier(EvqConst);
    515 
    516     if (type->isArray() && static_cast<size_t>(type->getArraySize()) != function.getParamCount()) {
    517         error(line, "array constructor needs one argument per array element", "constructor");
    518         return true;
    519     }
    520 
    521     if (arrayArg && op != EOpConstructStruct) {
    522         error(line, "constructing from a non-dereferenced array", "constructor");
    523         return true;
    524     }
    525 
    526     if (matrixInMatrix && !type->isArray()) {
    527         if (function.getParamCount() != 1) {
    528           error(line, "constructing matrix from matrix can only take one argument", "constructor");
    529           return true;
    530         }
    531     }
    532 
    533     if (overFull) {
    534         error(line, "too many arguments", "constructor");
    535         return true;
    536     }
    537 
    538     if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
    539         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
    540         return true;
    541     }
    542 
    543     if (!type->isMatrix() || !matrixInMatrix) {
    544         if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
    545             (op == EOpConstructStruct && size < type->getObjectSize())) {
    546             error(line, "not enough data provided for construction", "constructor");
    547             return true;
    548         }
    549     }
    550 
    551     TIntermTyped *typed = node ? node->getAsTyped() : 0;
    552     if (typed == 0) {
    553         error(line, "constructor argument does not have a type", "constructor");
    554         return true;
    555     }
    556     if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
    557         error(line, "cannot convert a sampler", "constructor");
    558         return true;
    559     }
    560     if (typed->getBasicType() == EbtVoid) {
    561         error(line, "cannot convert a void", "constructor");
    562         return true;
    563     }
    564 
    565     return false;
    566 }
    567 
    568 // This function checks to see if a void variable has been declared and raise an error message for such a case
    569 //
    570 // returns true in case of an error
    571 //
    572 bool TParseContext::voidErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& pubType)
    573 {
    574     if (pubType.type == EbtVoid) {
    575         error(line, "illegal use of type 'void'", identifier.c_str());
    576         return true;
    577     }
    578 
    579     return false;
    580 }
    581 
    582 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
    583 //
    584 // returns true in case of an error
    585 //
    586 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* type)
    587 {
    588     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
    589         error(line, "boolean expression expected", "");
    590         return true;
    591     }
    592 
    593     return false;
    594 }
    595 
    596 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
    597 //
    598 // returns true in case of an error
    599 //
    600 bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType)
    601 {
    602     if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
    603         error(line, "boolean expression expected", "");
    604         return true;
    605     }
    606 
    607     return false;
    608 }
    609 
    610 bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason)
    611 {
    612     if (pType.type == EbtStruct) {
    613         if (containsSampler(*pType.userDef)) {
    614             error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
    615 
    616             return true;
    617         }
    618 
    619         return false;
    620     } else if (IsSampler(pType.type)) {
    621         error(line, reason, getBasicString(pType.type));
    622 
    623         return true;
    624     }
    625 
    626     return false;
    627 }
    628 
    629 bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType)
    630 {
    631     if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
    632         pType.type == EbtStruct) {
    633         error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
    634 
    635         return true;
    636     }
    637 
    638     if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
    639         return true;
    640 
    641     return false;
    642 }
    643 
    644 bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type)
    645 {
    646     if ((qualifier == EvqOut || qualifier == EvqInOut) &&
    647              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
    648         error(line, "samplers cannot be output parameters", type.getBasicString());
    649         return true;
    650     }
    651 
    652     return false;
    653 }
    654 
    655 bool TParseContext::containsSampler(TType& type)
    656 {
    657     if (IsSampler(type.getBasicType()))
    658         return true;
    659 
    660     if (type.getBasicType() == EbtStruct) {
    661         const TFieldList& fields = type.getStruct()->fields();
    662         for (unsigned int i = 0; i < fields.size(); ++i) {
    663             if (containsSampler(*fields[i]->type()))
    664                 return true;
    665         }
    666     }
    667 
    668     return false;
    669 }
    670 
    671 //
    672 // Do size checking for an array type's size.
    673 //
    674 // Returns true if there was an error.
    675 //
    676 bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size)
    677 {
    678     TIntermConstantUnion* constant = expr->getAsConstantUnion();
    679     if (constant == 0 || constant->getBasicType() != EbtInt) {
    680         error(line, "array size must be a constant integer expression", "");
    681         return true;
    682     }
    683 
    684     size = constant->getIConst(0);
    685 
    686     if (size <= 0) {
    687         error(line, "array size must be a positive integer", "");
    688         size = 1;
    689         return true;
    690     }
    691 
    692     return false;
    693 }
    694 
    695 //
    696 // See if this qualifier can be an array.
    697 //
    698 // Returns true if there is an error.
    699 //
    700 bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type)
    701 {
    702     if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
    703         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
    704         return true;
    705     }
    706 
    707     return false;
    708 }
    709 
    710 //
    711 // See if this type can be an array.
    712 //
    713 // Returns true if there is an error.
    714 //
    715 bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type)
    716 {
    717     //
    718     // Can the type be an array?
    719     //
    720     if (type.array) {
    721         error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
    722         return true;
    723     }
    724 
    725     return false;
    726 }
    727 
    728 //
    729 // Do all the semantic checking for declaring an array, with and
    730 // without a size, and make the right changes to the symbol table.
    731 //
    732 // size == 0 means no specified size.
    733 //
    734 // Returns true if there was an error.
    735 //
    736 bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable)
    737 {
    738     //
    739     // Don't check for reserved word use until after we know it's not in the symbol table,
    740     // because reserved arrays can be redeclared.
    741     //
    742 
    743     bool builtIn = false;
    744     bool sameScope = false;
    745     TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
    746     if (symbol == 0 || !sameScope) {
    747         if (reservedErrorCheck(line, identifier))
    748             return true;
    749 
    750         variable = new TVariable(&identifier, TType(type));
    751 
    752         if (type.arraySize)
    753             variable->getType().setArraySize(type.arraySize);
    754 
    755         if (! symbolTable.insert(*variable)) {
    756             delete variable;
    757             error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
    758             return true;
    759         }
    760     } else {
    761         if (! symbol->isVariable()) {
    762             error(line, "variable expected", identifier.c_str());
    763             return true;
    764         }
    765 
    766         variable = static_cast<TVariable*>(symbol);
    767         if (! variable->getType().isArray()) {
    768             error(line, "redeclaring non-array as array", identifier.c_str());
    769             return true;
    770         }
    771         if (variable->getType().getArraySize() > 0) {
    772             error(line, "redeclaration of array with size", identifier.c_str());
    773             return true;
    774         }
    775 
    776         if (! variable->getType().sameElementType(TType(type))) {
    777             error(line, "redeclaration of array with a different type", identifier.c_str());
    778             return true;
    779         }
    780 
    781         if (type.arraySize)
    782             variable->getType().setArraySize(type.arraySize);
    783     }
    784 
    785     if (voidErrorCheck(line, identifier, type))
    786         return true;
    787 
    788     return false;
    789 }
    790 
    791 //
    792 // Enforce non-initializer type/qualifier rules.
    793 //
    794 // Returns true if there was an error.
    795 //
    796 bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array)
    797 {
    798     if (type.qualifier == EvqConst)
    799     {
    800         // Make the qualifier make sense.
    801         type.qualifier = EvqTemporary;
    802 
    803         if (array)
    804         {
    805             error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
    806         }
    807         else if (type.isStructureContainingArrays())
    808         {
    809             error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
    810         }
    811         else
    812         {
    813             error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
    814         }
    815 
    816         return true;
    817     }
    818 
    819     return false;
    820 }
    821 
    822 //
    823 // Do semantic checking for a variable declaration that has no initializer,
    824 // and update the symbol table.
    825 //
    826 // Returns true if there was an error.
    827 //
    828 bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable)
    829 {
    830     if (reservedErrorCheck(line, identifier))
    831         recover();
    832 
    833     variable = new TVariable(&identifier, TType(type));
    834 
    835     if (! symbolTable.insert(*variable)) {
    836         error(line, "redefinition", variable->getName().c_str());
    837         delete variable;
    838         variable = 0;
    839         return true;
    840     }
    841 
    842     if (voidErrorCheck(line, identifier, type))
    843         return true;
    844 
    845     return false;
    846 }
    847 
    848 bool TParseContext::paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
    849 {
    850     if (qualifier != EvqConst && qualifier != EvqTemporary) {
    851         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
    852         return true;
    853     }
    854     if (qualifier == EvqConst && paramQualifier != EvqIn) {
    855         error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
    856         return true;
    857     }
    858 
    859     if (qualifier == EvqConst)
    860         type->setQualifier(EvqConstReadOnly);
    861     else
    862         type->setQualifier(paramQualifier);
    863 
    864     return false;
    865 }
    866 
    867 bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& extension)
    868 {
    869     const TExtensionBehavior& extBehavior = extensionBehavior();
    870     TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
    871     if (iter == extBehavior.end()) {
    872         error(line, "extension", extension.c_str(), "is not supported");
    873         return true;
    874     }
    875     // In GLSL ES, an extension's default behavior is "disable".
    876     if (iter->second == EBhDisable || iter->second == EBhUndefined) {
    877         error(line, "extension", extension.c_str(), "is disabled");
    878         return true;
    879     }
    880     if (iter->second == EBhWarn) {
    881         warning(line, "extension", extension.c_str(), "is being used");
    882         return false;
    883     }
    884 
    885     return false;
    886 }
    887 
    888 bool TParseContext::supportsExtension(const char* extension)
    889 {
    890     const TExtensionBehavior& extbehavior = extensionBehavior();
    891     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
    892     return (iter != extbehavior.end());
    893 }
    894 
    895 bool TParseContext::isExtensionEnabled(const char* extension) const
    896 {
    897     const TExtensionBehavior& extbehavior = extensionBehavior();
    898     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
    899 
    900     if (iter == extbehavior.end())
    901     {
    902         return false;
    903     }
    904 
    905     return (iter->second == EBhEnable || iter->second == EBhRequire);
    906 }
    907 
    908 /////////////////////////////////////////////////////////////////////////////////
    909 //
    910 // Non-Errors.
    911 //
    912 /////////////////////////////////////////////////////////////////////////////////
    913 
    914 //
    915 // Look up a function name in the symbol table, and make sure it is a function.
    916 //
    917 // Return the function symbol if found, otherwise 0.
    918 //
    919 const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn)
    920 {
    921     // First find by unmangled name to check whether the function name has been
    922     // hidden by a variable name or struct typename.
    923     // If a function is found, check for one with a matching argument list.
    924     const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
    925     if (symbol == 0 || symbol->isFunction()) {
    926         symbol = symbolTable.find(call->getMangledName(), builtIn);
    927     }
    928 
    929     if (symbol == 0) {
    930         error(line, "no matching overloaded function found", call->getName().c_str());
    931         return 0;
    932     }
    933 
    934     if (!symbol->isFunction()) {
    935         error(line, "function name expected", call->getName().c_str());
    936         return 0;
    937     }
    938 
    939     return static_cast<const TFunction*>(symbol);
    940 }
    941 
    942 //
    943 // Initializers show up in several places in the grammar.  Have one set of
    944 // code to handle them here.
    945 //
    946 bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType,
    947                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
    948 {
    949     TType type = TType(pType);
    950 
    951     if (variable == 0) {
    952         if (reservedErrorCheck(line, identifier))
    953             return true;
    954 
    955         if (voidErrorCheck(line, identifier, pType))
    956             return true;
    957 
    958         //
    959         // add variable to symbol table
    960         //
    961         variable = new TVariable(&identifier, type);
    962         if (! symbolTable.insert(*variable)) {
    963             error(line, "redefinition", variable->getName().c_str());
    964             return true;
    965             // don't delete variable, it's used by error recovery, and the pool
    966             // pop will take care of the memory
    967         }
    968     }
    969 
    970     //
    971     // identifier must be of type constant, a global, or a temporary
    972     //
    973     TQualifier qualifier = variable->getType().getQualifier();
    974     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
    975         error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
    976         return true;
    977     }
    978     //
    979     // test for and propagate constant
    980     //
    981 
    982     if (qualifier == EvqConst) {
    983         if (qualifier != initializer->getType().getQualifier()) {
    984             std::stringstream extraInfoStream;
    985             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
    986             std::string extraInfo = extraInfoStream.str();
    987             error(line, " assigning non-constant to", "=", extraInfo.c_str());
    988             variable->getType().setQualifier(EvqTemporary);
    989             return true;
    990         }
    991         if (type != initializer->getType()) {
    992             error(line, " non-matching types for const initializer ",
    993                 variable->getType().getQualifierString());
    994             variable->getType().setQualifier(EvqTemporary);
    995             return true;
    996         }
    997         if (initializer->getAsConstantUnion()) {
    998             variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
    999         } else if (initializer->getAsSymbolNode()) {
   1000             const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
   1001             const TVariable* tVar = static_cast<const TVariable*>(symbol);
   1002 
   1003             ConstantUnion* constArray = tVar->getConstPointer();
   1004             variable->shareConstPointer(constArray);
   1005         } else {
   1006             std::stringstream extraInfoStream;
   1007             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
   1008             std::string extraInfo = extraInfoStream.str();
   1009             error(line, " cannot assign to", "=", extraInfo.c_str());
   1010             variable->getType().setQualifier(EvqTemporary);
   1011             return true;
   1012         }
   1013     }
   1014 
   1015     if (qualifier != EvqConst) {
   1016         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
   1017         intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
   1018         if (intermNode == 0) {
   1019             assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
   1020             return true;
   1021         }
   1022     } else
   1023         intermNode = 0;
   1024 
   1025     return false;
   1026 }
   1027 
   1028 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
   1029 {
   1030     ASSERT(aggrNode != NULL);
   1031     if (!aggrNode->isConstructor())
   1032         return false;
   1033 
   1034     bool allConstant = true;
   1035 
   1036     // check if all the child nodes are constants so that they can be inserted into
   1037     // the parent node
   1038     TIntermSequence &sequence = aggrNode->getSequence() ;
   1039     for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
   1040         if (!(*p)->getAsTyped()->getAsConstantUnion())
   1041             return false;
   1042     }
   1043 
   1044     return allConstant;
   1045 }
   1046 
   1047 // This function is used to test for the correctness of the parameters passed to various constructor functions
   1048 // and also convert them to the right datatype if it is allowed and required.
   1049 //
   1050 // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
   1051 //
   1052 TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line)
   1053 {
   1054     if (node == 0)
   1055         return 0;
   1056 
   1057     TIntermAggregate* aggrNode = node->getAsAggregate();
   1058 
   1059     TFieldList::const_iterator memberFields;
   1060     if (op == EOpConstructStruct)
   1061         memberFields = type->getStruct()->fields().begin();
   1062 
   1063     TType elementType = *type;
   1064     if (type->isArray())
   1065         elementType.clearArrayness();
   1066 
   1067     bool singleArg;
   1068     if (aggrNode) {
   1069         if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
   1070             singleArg = true;
   1071         else
   1072             singleArg = false;
   1073     } else
   1074         singleArg = true;
   1075 
   1076     TIntermTyped *newNode;
   1077     if (singleArg) {
   1078         // If structure constructor or array constructor is being called
   1079         // for only one parameter inside the structure, we need to call constructStruct function once.
   1080         if (type->isArray())
   1081             newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
   1082         else if (op == EOpConstructStruct)
   1083             newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false);
   1084         else
   1085             newNode = constructBuiltIn(type, op, node, node->getLine(), false);
   1086 
   1087         if (newNode && newNode->getAsAggregate()) {
   1088             TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
   1089             if (constConstructor)
   1090                 return constConstructor;
   1091         }
   1092 
   1093         return newNode;
   1094     }
   1095 
   1096     //
   1097     // Handle list of arguments.
   1098     //
   1099     TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
   1100     // if the structure constructor contains more than one parameter, then construct
   1101     // each parameter
   1102 
   1103     int paramCount = 0;  // keeps a track of the constructor parameter number being checked
   1104 
   1105     // for each parameter to the constructor call, check to see if the right type is passed or convert them
   1106     // to the right type if possible (and allowed).
   1107     // for structure constructors, just check if the right type is passed, no conversion is allowed.
   1108 
   1109     for (TIntermSequence::iterator p = sequenceVector.begin();
   1110                                    p != sequenceVector.end(); p++, paramCount++) {
   1111         if (type->isArray())
   1112             newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
   1113         else if (op == EOpConstructStruct)
   1114             newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true);
   1115         else
   1116             newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
   1117 
   1118         if (newNode) {
   1119             *p = newNode;
   1120         }
   1121     }
   1122 
   1123     TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
   1124     TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
   1125     if (constConstructor)
   1126         return constConstructor;
   1127 
   1128     return constructor;
   1129 }
   1130 
   1131 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
   1132 {
   1133     bool canBeFolded = areAllChildConst(aggrNode);
   1134     aggrNode->setType(type);
   1135     if (canBeFolded) {
   1136         bool returnVal = false;
   1137         ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
   1138         if (aggrNode->getSequence().size() == 1)  {
   1139             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type, true);
   1140         }
   1141         else {
   1142             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type);
   1143         }
   1144         if (returnVal)
   1145             return 0;
   1146 
   1147         return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
   1148     }
   1149 
   1150     return 0;
   1151 }
   1152 
   1153 // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
   1154 // for the parameter to the constructor (passed to this function). Essentially, it converts
   1155 // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
   1156 // float, then float is converted to int.
   1157 //
   1158 // Returns 0 for an error or the constructed node.
   1159 //
   1160 TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset)
   1161 {
   1162     TIntermTyped* newNode;
   1163     TOperator basicOp;
   1164 
   1165     //
   1166     // First, convert types as needed.
   1167     //
   1168     switch (op) {
   1169     case EOpConstructVec2:
   1170     case EOpConstructVec3:
   1171     case EOpConstructVec4:
   1172     case EOpConstructMat2:
   1173     case EOpConstructMat3:
   1174     case EOpConstructMat4:
   1175     case EOpConstructFloat:
   1176         basicOp = EOpConstructFloat;
   1177         break;
   1178 
   1179     case EOpConstructIVec2:
   1180     case EOpConstructIVec3:
   1181     case EOpConstructIVec4:
   1182     case EOpConstructInt:
   1183         basicOp = EOpConstructInt;
   1184         break;
   1185 
   1186     case EOpConstructBVec2:
   1187     case EOpConstructBVec3:
   1188     case EOpConstructBVec4:
   1189     case EOpConstructBool:
   1190         basicOp = EOpConstructBool;
   1191         break;
   1192 
   1193     default:
   1194         error(line, "unsupported construction", "");
   1195         recover();
   1196 
   1197         return 0;
   1198     }
   1199     newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
   1200     if (newNode == 0) {
   1201         error(line, "can't convert", "constructor");
   1202         return 0;
   1203     }
   1204 
   1205     //
   1206     // Now, if there still isn't an operation to do the construction, and we need one, add one.
   1207     //
   1208 
   1209     // Otherwise, skip out early.
   1210     if (subset || (newNode != node && newNode->getType() == *type))
   1211         return newNode;
   1212 
   1213     // setAggregateOperator will insert a new node for the constructor, as needed.
   1214     return intermediate.setAggregateOperator(newNode, op, line);
   1215 }
   1216 
   1217 // This function tests for the type of the parameters to the structures constructors. Raises
   1218 // an error message if the expected type does not match the parameter passed to the constructor.
   1219 //
   1220 // Returns 0 for an error or the input node itself if the expected and the given parameter types match.
   1221 //
   1222 TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset)
   1223 {
   1224     if (*type == node->getAsTyped()->getType()) {
   1225         if (subset)
   1226             return node->getAsTyped();
   1227         else
   1228             return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
   1229     } else {
   1230         std::stringstream extraInfoStream;
   1231         extraInfoStream << "cannot convert parameter " << paramCount
   1232                         << " from '" << node->getAsTyped()->getType().getBasicString()
   1233                         << "' to '" << type->getBasicString() << "'";
   1234         std::string extraInfo = extraInfoStream.str();
   1235         error(line, "", "constructor", extraInfo.c_str());
   1236         recover();
   1237     }
   1238 
   1239     return 0;
   1240 }
   1241 
   1242 //
   1243 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
   1244 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
   1245 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
   1246 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
   1247 // a constant matrix.
   1248 //
   1249 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line)
   1250 {
   1251     TIntermTyped* typedNode;
   1252     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1253 
   1254     ConstantUnion *unionArray;
   1255     if (tempConstantNode) {
   1256         unionArray = tempConstantNode->getUnionArrayPointer();
   1257 
   1258         if (!unionArray) {
   1259             return node;
   1260         }
   1261     } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
   1262         error(line, "Cannot offset into the vector", "Error");
   1263         recover();
   1264 
   1265         return 0;
   1266     }
   1267 
   1268     ConstantUnion* constArray = new ConstantUnion[fields.num];
   1269 
   1270     for (int i = 0; i < fields.num; i++) {
   1271         if (fields.offsets[i] >= node->getType().getNominalSize()) {
   1272             std::stringstream extraInfoStream;
   1273             extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
   1274             std::string extraInfo = extraInfoStream.str();
   1275             error(line, "", "[", extraInfo.c_str());
   1276             recover();
   1277             fields.offsets[i] = 0;
   1278         }
   1279 
   1280         constArray[i] = unionArray[fields.offsets[i]];
   1281 
   1282     }
   1283     typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
   1284     return typedNode;
   1285 }
   1286 
   1287 //
   1288 // This function returns the column being accessed from a constant matrix. The values are retrieved from
   1289 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
   1290 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
   1291 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
   1292 //
   1293 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line)
   1294 {
   1295     TIntermTyped* typedNode;
   1296     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1297 
   1298     if (index >= node->getType().getNominalSize()) {
   1299         std::stringstream extraInfoStream;
   1300         extraInfoStream << "matrix field selection out of range '" << index << "'";
   1301         std::string extraInfo = extraInfoStream.str();
   1302         error(line, "", "[", extraInfo.c_str());
   1303         recover();
   1304         index = 0;
   1305     }
   1306 
   1307     if (tempConstantNode) {
   1308          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
   1309          int size = tempConstantNode->getType().getNominalSize();
   1310          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
   1311     } else {
   1312         error(line, "Cannot offset into the matrix", "Error");
   1313         recover();
   1314 
   1315         return 0;
   1316     }
   1317 
   1318     return typedNode;
   1319 }
   1320 
   1321 
   1322 //
   1323 // This function returns an element of an array accessed from a constant array. The values are retrieved from
   1324 // the symbol table and parse-tree is built for the type of the element. The input
   1325 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
   1326 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
   1327 //
   1328 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line)
   1329 {
   1330     TIntermTyped* typedNode;
   1331     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1332     TType arrayElementType = node->getType();
   1333     arrayElementType.clearArrayness();
   1334 
   1335     if (index >= node->getType().getArraySize()) {
   1336         std::stringstream extraInfoStream;
   1337         extraInfoStream << "array field selection out of range '" << index << "'";
   1338         std::string extraInfo = extraInfoStream.str();
   1339         error(line, "", "[", extraInfo.c_str());
   1340         recover();
   1341         index = 0;
   1342     }
   1343 
   1344     if (tempConstantNode) {
   1345          size_t arrayElementSize = arrayElementType.getObjectSize();
   1346          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
   1347          typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
   1348     } else {
   1349         error(line, "Cannot offset into the array", "Error");
   1350         recover();
   1351 
   1352         return 0;
   1353     }
   1354 
   1355     return typedNode;
   1356 }
   1357 
   1358 
   1359 //
   1360 // This function returns the value of a particular field inside a constant structure from the symbol table.
   1361 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
   1362 // function and returns the parse-tree with the values of the embedded/nested struct.
   1363 //
   1364 TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line)
   1365 {
   1366     const TFieldList& fields = node->getType().getStruct()->fields();
   1367 
   1368     size_t instanceSize = 0;
   1369     for (size_t index = 0; index < fields.size(); ++index) {
   1370         if (fields[index]->name() == identifier) {
   1371             break;
   1372         } else {
   1373             instanceSize += fields[index]->type()->getObjectSize();
   1374         }
   1375     }
   1376 
   1377     TIntermTyped* typedNode = 0;
   1378     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
   1379     if (tempConstantNode) {
   1380          ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
   1381 
   1382          typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
   1383     } else {
   1384         error(line, "Cannot offset into the structure", "Error");
   1385         recover();
   1386 
   1387         return 0;
   1388     }
   1389 
   1390     return typedNode;
   1391 }
   1392 
   1393 bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier)
   1394 {
   1395     ++structNestingLevel;
   1396 
   1397     // Embedded structure definitions are not supported per GLSL ES spec.
   1398     // They aren't allowed in GLSL either, but we need to detect this here
   1399     // so we don't rely on the GLSL compiler to catch it.
   1400     if (structNestingLevel > 1) {
   1401         error(line, "", "Embedded struct definitions are not allowed");
   1402         return true;
   1403     }
   1404 
   1405     return false;
   1406 }
   1407 
   1408 void TParseContext::exitStructDeclaration()
   1409 {
   1410     --structNestingLevel;
   1411 }
   1412 
   1413 namespace {
   1414 
   1415 const int kWebGLMaxStructNesting = 4;
   1416 
   1417 }  // namespace
   1418 
   1419 bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field)
   1420 {
   1421     if (!isWebGLBasedSpec(shaderSpec)) {
   1422         return false;
   1423     }
   1424 
   1425     if (field.type()->getBasicType() != EbtStruct) {
   1426         return false;
   1427     }
   1428 
   1429     // We're already inside a structure definition at this point, so add
   1430     // one to the field's struct nesting.
   1431     if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting) {
   1432         std::stringstream extraInfoStream;
   1433         extraInfoStream << "Reference of struct type " << field.name()
   1434                         << " exceeds maximum struct nesting of " << kWebGLMaxStructNesting;
   1435         std::string extraInfo = extraInfoStream.str();
   1436         error(line, "", "", extraInfo.c_str());
   1437         return true;
   1438     }
   1439 
   1440     return false;
   1441 }
   1442 
   1443 //
   1444 // Parse an array index expression
   1445 //
   1446 TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression)
   1447 {
   1448     TIntermTyped *indexedExpression = NULL;
   1449 
   1450     if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
   1451     {
   1452         if (baseExpression->getAsSymbolNode())
   1453         {
   1454             error(location, " left of '[' is not of type array, matrix, or vector ", baseExpression->getAsSymbolNode()->getSymbol().c_str());
   1455         }
   1456         else
   1457         {
   1458             error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
   1459         }
   1460         recover();
   1461     }
   1462 
   1463     if (indexExpression->getQualifier() == EvqConst)
   1464     {
   1465         int index = indexExpression->getAsConstantUnion()->getIConst(0);
   1466         if (index < 0)
   1467         {
   1468             std::stringstream infoStream;
   1469             infoStream << index;
   1470             std::string info = infoStream.str();
   1471             error(location, "negative index", info.c_str());
   1472             recover();
   1473             index = 0;
   1474         }
   1475         if (baseExpression->getType().getQualifier() == EvqConst)
   1476         {
   1477             if (baseExpression->isArray())
   1478             {
   1479                 // constant folding for arrays
   1480                 indexedExpression = addConstArrayNode(index, baseExpression, location);
   1481             }
   1482             else if (baseExpression->isVector())
   1483             {
   1484                 // constant folding for vectors
   1485                 TVectorFields fields;
   1486                 fields.num = 1;
   1487                 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
   1488                 indexedExpression = addConstVectorNode(fields, baseExpression, location);
   1489             }
   1490             else if (baseExpression->isMatrix())
   1491             {
   1492                 // constant folding for matrices
   1493                 indexedExpression = addConstMatrixNode(index, baseExpression, location);
   1494             }
   1495         }
   1496         else
   1497         {
   1498             if (baseExpression->isArray())
   1499             {
   1500                 if (index >= baseExpression->getType().getArraySize())
   1501                 {
   1502                     std::stringstream extraInfoStream;
   1503                     extraInfoStream << "array index out of range '" << index << "'";
   1504                     std::string extraInfo = extraInfoStream.str();
   1505                     error(location, "", "[", extraInfo.c_str());
   1506                     recover();
   1507                     index = baseExpression->getType().getArraySize() - 1;
   1508                 }
   1509                 else if (baseExpression->getQualifier() == EvqFragData && index > 0 && !isExtensionEnabled("GL_EXT_draw_buffers"))
   1510                 {
   1511                     error(location, "", "[", "array indexes for gl_FragData must be zero when GL_EXT_draw_buffers is disabled");
   1512                     recover();
   1513                     index = 0;
   1514                 }
   1515             }
   1516             else if ((baseExpression->isVector() || baseExpression->isMatrix()) && baseExpression->getType().getNominalSize() <= index)
   1517             {
   1518                 std::stringstream extraInfoStream;
   1519                 extraInfoStream << "field selection out of range '" << index << "'";
   1520                 std::string extraInfo = extraInfoStream.str();
   1521                 error(location, "", "[", extraInfo.c_str());
   1522                 recover();
   1523                 index = baseExpression->getType().getNominalSize() - 1;
   1524             }
   1525 
   1526             indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
   1527             indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
   1528         }
   1529     }
   1530     else
   1531     {
   1532         indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
   1533     }
   1534 
   1535     if (indexedExpression == 0)
   1536     {
   1537         ConstantUnion *unionArray = new ConstantUnion[1];
   1538         unionArray->setFConst(0.0f);
   1539         indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), location);
   1540     }
   1541     else if (baseExpression->isArray())
   1542     {
   1543         const TType &baseType = baseExpression->getType();
   1544         if (baseType.getStruct())
   1545         {
   1546             TType copyOfType(baseType.getStruct());
   1547             indexedExpression->setType(copyOfType);
   1548         }
   1549         else
   1550         {
   1551             indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix()));
   1552         }
   1553 
   1554         if (baseExpression->getType().getQualifier() == EvqConst)
   1555         {
   1556             indexedExpression->getTypePointer()->setQualifier(EvqConst);
   1557         }
   1558     }
   1559     else if (baseExpression->isMatrix())
   1560     {
   1561         TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
   1562         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize()));
   1563     }
   1564     else if (baseExpression->isVector())
   1565     {
   1566         TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary;
   1567         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
   1568     }
   1569     else
   1570     {
   1571         indexedExpression->setType(baseExpression->getType());
   1572     }
   1573 
   1574     return indexedExpression;
   1575 }
   1576 
   1577 //
   1578 // Parse an array of strings using yyparse.
   1579 //
   1580 // Returns 0 for success.
   1581 //
   1582 int PaParseStrings(size_t count, const char* const string[], const int length[],
   1583                    TParseContext* context) {
   1584     if ((count == 0) || (string == NULL))
   1585         return 1;
   1586 
   1587     if (glslang_initialize(context))
   1588         return 1;
   1589 
   1590     int error = glslang_scan(count, string, length, context);
   1591     if (!error)
   1592         error = glslang_parse(context);
   1593 
   1594     glslang_finalize(context);
   1595 
   1596     return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
   1597 }
   1598 
   1599 
   1600 
   1601