LCOV - code coverage report
Current view: directory - gfx/angle/src/compiler - ParseHelper.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 731 0 0.0 %
Date: 2012-06-02 Functions: 54 0 0.0 %

       1                 : //
       2                 : // Copyright (c) 2002-2010 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/osinclude.h"
      14                 : #include "compiler/InitializeParseContext.h"
      15                 : 
      16                 : extern "C" {
      17                 : extern int InitPreprocessor();
      18                 : extern int FinalizePreprocessor();
      19                 : extern void PredefineIntMacro(const char *name, int value);
      20                 : }
      21                 : 
      22               0 : static void ReportInfo(TInfoSinkBase& sink,
      23                 :                        TPrefixType type, TSourceLoc loc,
      24                 :                        const char* reason, const char* token, 
      25                 :                        const char* extraInfo)
      26                 : {
      27                 :     /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
      28               0 :     sink.prefix(type);
      29               0 :     sink.location(loc);
      30               0 :     sink << "'" << token <<  "' : " << reason << " " << extraInfo << "\n";
      31               0 : }
      32                 : 
      33               0 : static void DefineExtensionMacros(const TExtensionBehavior& extBehavior)
      34                 : {
      35               0 :     for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
      36               0 :          iter != extBehavior.end(); ++iter) {
      37               0 :         PredefineIntMacro(iter->first.c_str(), 1);
      38                 :     }
      39               0 : }
      40                 : 
      41                 : ///////////////////////////////////////////////////////////////////////
      42                 : //
      43                 : // Sub- vector and matrix fields
      44                 : //
      45                 : ////////////////////////////////////////////////////////////////////////
      46                 : 
      47                 : //
      48                 : // Look at a '.' field selector string and change it into offsets
      49                 : // for a vector.
      50                 : //
      51               0 : bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
      52                 : {
      53               0 :     fields.num = (int) compString.size();
      54               0 :     if (fields.num > 4) {
      55               0 :         error(line, "illegal vector field selection", compString.c_str(), "");
      56               0 :         return false;
      57                 :     }
      58                 : 
      59                 :     enum {
      60                 :         exyzw,
      61                 :         ergba,
      62                 :         estpq,
      63                 :     } fieldSet[4];
      64                 : 
      65               0 :     for (int i = 0; i < fields.num; ++i) {
      66               0 :         switch (compString[i])  {
      67                 :         case 'x': 
      68               0 :             fields.offsets[i] = 0;
      69               0 :             fieldSet[i] = exyzw;
      70               0 :             break;
      71                 :         case 'r': 
      72               0 :             fields.offsets[i] = 0;
      73               0 :             fieldSet[i] = ergba;
      74               0 :             break;
      75                 :         case 's':
      76               0 :             fields.offsets[i] = 0;
      77               0 :             fieldSet[i] = estpq;
      78               0 :             break;
      79                 :         case 'y': 
      80               0 :             fields.offsets[i] = 1;
      81               0 :             fieldSet[i] = exyzw;
      82               0 :             break;
      83                 :         case 'g': 
      84               0 :             fields.offsets[i] = 1;
      85               0 :             fieldSet[i] = ergba;
      86               0 :             break;
      87                 :         case 't':
      88               0 :             fields.offsets[i] = 1;
      89               0 :             fieldSet[i] = estpq;
      90               0 :             break;
      91                 :         case 'z': 
      92               0 :             fields.offsets[i] = 2;
      93               0 :             fieldSet[i] = exyzw;
      94               0 :             break;
      95                 :         case 'b': 
      96               0 :             fields.offsets[i] = 2;
      97               0 :             fieldSet[i] = ergba;
      98               0 :             break;
      99                 :         case 'p':
     100               0 :             fields.offsets[i] = 2;
     101               0 :             fieldSet[i] = estpq;
     102               0 :             break;
     103                 :         
     104                 :         case 'w': 
     105               0 :             fields.offsets[i] = 3;
     106               0 :             fieldSet[i] = exyzw;
     107               0 :             break;
     108                 :         case 'a': 
     109               0 :             fields.offsets[i] = 3;
     110               0 :             fieldSet[i] = ergba;
     111               0 :             break;
     112                 :         case 'q':
     113               0 :             fields.offsets[i] = 3;
     114               0 :             fieldSet[i] = estpq;
     115               0 :             break;
     116                 :         default:
     117               0 :             error(line, "illegal vector field selection", compString.c_str(), "");
     118               0 :             return false;
     119                 :         }
     120                 :     }
     121                 : 
     122               0 :     for (int i = 0; i < fields.num; ++i) {
     123               0 :         if (fields.offsets[i] >= vecSize) {
     124               0 :             error(line, "vector field selection out of range",  compString.c_str(), "");
     125               0 :             return false;
     126                 :         }
     127                 : 
     128               0 :         if (i > 0) {
     129               0 :             if (fieldSet[i] != fieldSet[i-1]) {
     130               0 :                 error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
     131               0 :                 return false;
     132                 :             }
     133                 :         }
     134                 :     }
     135                 : 
     136               0 :     return true;
     137                 : }
     138                 : 
     139                 : 
     140                 : //
     141                 : // Look at a '.' field selector string and change it into offsets
     142                 : // for a matrix.
     143                 : //
     144               0 : bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
     145                 : {
     146               0 :     fields.wholeRow = false;
     147               0 :     fields.wholeCol = false;
     148               0 :     fields.row = -1;
     149               0 :     fields.col = -1;
     150                 : 
     151               0 :     if (compString.size() != 2) {
     152               0 :         error(line, "illegal length of matrix field selection", compString.c_str(), "");
     153               0 :         return false;
     154                 :     }
     155                 : 
     156               0 :     if (compString[0] == '_') {
     157               0 :         if (compString[1] < '0' || compString[1] > '3') {
     158               0 :             error(line, "illegal matrix field selection", compString.c_str(), "");
     159               0 :             return false;
     160                 :         }
     161               0 :         fields.wholeCol = true;
     162               0 :         fields.col = compString[1] - '0';
     163               0 :     } else if (compString[1] == '_') {
     164               0 :         if (compString[0] < '0' || compString[0] > '3') {
     165               0 :             error(line, "illegal matrix field selection", compString.c_str(), "");
     166               0 :             return false;
     167                 :         }
     168               0 :         fields.wholeRow = true;
     169               0 :         fields.row = compString[0] - '0';
     170                 :     } else {
     171               0 :         if (compString[0] < '0' || compString[0] > '3' ||
     172               0 :             compString[1] < '0' || compString[1] > '3') {
     173               0 :             error(line, "illegal matrix field selection", compString.c_str(), "");
     174               0 :             return false;
     175                 :         }
     176               0 :         fields.row = compString[0] - '0';
     177               0 :         fields.col = compString[1] - '0';
     178                 :     }
     179                 : 
     180               0 :     if (fields.row >= matSize || fields.col >= matSize) {
     181               0 :         error(line, "matrix field selection out of range", compString.c_str(), "");
     182               0 :         return false;
     183                 :     }
     184                 : 
     185               0 :     return true;
     186                 : }
     187                 : 
     188                 : ///////////////////////////////////////////////////////////////////////
     189                 : //
     190                 : // Errors
     191                 : //
     192                 : ////////////////////////////////////////////////////////////////////////
     193                 : 
     194                 : //
     195                 : // Track whether errors have occurred.
     196                 : //
     197               0 : void TParseContext::recover()
     198                 : {
     199               0 : }
     200                 : 
     201                 : //
     202                 : // Used by flex/bison to output all syntax and parsing errors.
     203                 : //
     204               0 : void TParseContext::error(TSourceLoc loc,
     205                 :                           const char* reason, const char* token, 
     206                 :                           const char* extraInfoFormat, ...)
     207                 : {
     208                 :     char extraInfo[512];
     209                 :     va_list marker;
     210               0 :     va_start(marker, extraInfoFormat);
     211               0 :     vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker);
     212                 : 
     213               0 :     ReportInfo(infoSink.info, EPrefixError, loc, reason, token, extraInfo);
     214                 : 
     215               0 :     va_end(marker);
     216               0 :     ++numErrors;
     217               0 : }
     218                 : 
     219               0 : void TParseContext::warning(TSourceLoc loc,
     220                 :                             const char* reason, const char* token,
     221                 :                             const char* extraInfoFormat, ...) {
     222                 :     char extraInfo[512];
     223                 :     va_list marker;
     224               0 :     va_start(marker, extraInfoFormat);
     225               0 :     vsnprintf(extraInfo, sizeof(extraInfo), extraInfoFormat, marker);
     226                 : 
     227               0 :     ReportInfo(infoSink.info, EPrefixWarning, loc, reason, token, extraInfo);
     228                 : 
     229               0 :     va_end(marker);
     230               0 : }
     231                 : 
     232                 : //
     233                 : // Same error message for all places assignments don't work.
     234                 : //
     235               0 : void TParseContext::assignError(int line, const char* op, TString left, TString right)
     236                 : {
     237                 :     error(line, "", op, "cannot convert from '%s' to '%s'",
     238               0 :           right.c_str(), left.c_str());
     239               0 : }
     240                 : 
     241                 : //
     242                 : // Same error message for all places unary operations don't work.
     243                 : //
     244               0 : void TParseContext::unaryOpError(int line, const char* op, TString operand)
     245                 : {
     246                 :    error(line, " wrong operand type", op, 
     247                 :           "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
     248               0 :           op, operand.c_str());
     249               0 : }
     250                 : 
     251                 : //
     252                 : // Same error message for all binary operations don't work.
     253                 : //
     254               0 : void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
     255                 : {
     256                 :     error(line, " wrong operand types ", op, 
     257                 :             "no operation '%s' exists that takes a left-hand operand of type '%s' and "
     258                 :             "a right operand of type '%s' (or there is no acceptable conversion)", 
     259               0 :             op, left.c_str(), right.c_str());
     260               0 : }
     261                 : 
     262               0 : bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
     263               0 :     if (!checksPrecisionErrors)
     264               0 :         return false;
     265               0 :     switch( type ){
     266                 :     case EbtFloat:
     267               0 :         if( precision == EbpUndefined ){
     268               0 :             error( line, "No precision specified for (float)", "", "" );
     269               0 :             return true;
     270                 :         }
     271               0 :         break;
     272                 :     case EbtInt:
     273               0 :         if( precision == EbpUndefined ){
     274               0 :             error( line, "No precision specified (int)", "", "" );
     275               0 :             return true;
     276                 :         }
     277               0 :         break;
     278                 :     default:
     279               0 :         return false;
     280                 :     }
     281               0 :     return false;
     282                 : }
     283                 : 
     284                 : //
     285                 : // Both test and if necessary, spit out an error, to see if the node is really
     286                 : // an l-value that can be operated on this way.
     287                 : //
     288                 : // Returns true if the was an error.
     289                 : //
     290               0 : bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
     291                 : {
     292               0 :     TIntermSymbol* symNode = node->getAsSymbolNode();
     293               0 :     TIntermBinary* binaryNode = node->getAsBinaryNode();
     294                 : 
     295               0 :     if (binaryNode) {
     296                 :         bool errorReturn;
     297                 : 
     298               0 :         switch(binaryNode->getOp()) {
     299                 :         case EOpIndexDirect:
     300                 :         case EOpIndexIndirect:
     301                 :         case EOpIndexDirectStruct:
     302               0 :             return lValueErrorCheck(line, op, binaryNode->getLeft());
     303                 :         case EOpVectorSwizzle:
     304               0 :             errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
     305               0 :             if (!errorReturn) {
     306               0 :                 int offset[4] = {0,0,0,0};
     307                 : 
     308               0 :                 TIntermTyped* rightNode = binaryNode->getRight();
     309               0 :                 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
     310                 :                 
     311               0 :                 for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); 
     312               0 :                                                p != aggrNode->getSequence().end(); p++) {
     313               0 :                     int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
     314               0 :                     offset[value]++;     
     315               0 :                     if (offset[value] > 1) {
     316               0 :                         error(line, " l-value of swizzle cannot have duplicate components", op, "", "");
     317                 : 
     318               0 :                         return true;
     319                 :                     }
     320                 :                 }
     321                 :             } 
     322                 : 
     323               0 :             return errorReturn;
     324                 :         default: 
     325                 :             break;
     326                 :         }
     327               0 :         error(line, " l-value required", op, "", "");
     328                 : 
     329               0 :         return true;
     330                 :     }
     331                 : 
     332                 : 
     333               0 :     const char* symbol = 0;
     334               0 :     if (symNode != 0)
     335               0 :         symbol = symNode->getSymbol().c_str();
     336                 : 
     337               0 :     const char* message = 0;
     338               0 :     switch (node->getQualifier()) {
     339               0 :     case EvqConst:          message = "can't modify a const";        break;
     340               0 :     case EvqConstReadOnly:  message = "can't modify a const";        break;
     341               0 :     case EvqAttribute:      message = "can't modify an attribute";   break;
     342               0 :     case EvqUniform:        message = "can't modify a uniform";      break;
     343               0 :     case EvqVaryingIn:      message = "can't modify a varying";      break;
     344               0 :     case EvqInput:          message = "can't modify an input";       break;
     345               0 :     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
     346               0 :     case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
     347               0 :     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
     348                 :     default:
     349                 : 
     350                 :         //
     351                 :         // Type that can't be written to?
     352                 :         //
     353               0 :         switch (node->getBasicType()) {
     354                 :         case EbtSampler2D:
     355                 :         case EbtSamplerCube:
     356               0 :             message = "can't modify a sampler";
     357               0 :             break;
     358                 :         case EbtVoid:
     359               0 :             message = "can't modify void";
     360               0 :             break;
     361                 :         default: 
     362               0 :             break;
     363                 :         }
     364                 :     }
     365                 : 
     366               0 :     if (message == 0 && binaryNode == 0 && symNode == 0) {
     367               0 :         error(line, " l-value required", op, "", "");
     368                 : 
     369               0 :         return true;
     370                 :     }
     371                 : 
     372                 : 
     373                 :     //
     374                 :     // Everything else is okay, no error.
     375                 :     //
     376               0 :     if (message == 0)
     377               0 :         return false;
     378                 : 
     379                 :     //
     380                 :     // If we get here, we have an error and a message.
     381                 :     //
     382               0 :     if (symNode)
     383               0 :         error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
     384                 :     else
     385               0 :         error(line, " l-value required", op, "(%s)", message);
     386                 : 
     387               0 :     return true;
     388                 : }
     389                 : 
     390                 : //
     391                 : // Both test, and if necessary spit out an error, to see if the node is really
     392                 : // a constant.
     393                 : //
     394                 : // Returns true if the was an error.
     395                 : //
     396               0 : bool TParseContext::constErrorCheck(TIntermTyped* node)
     397                 : {
     398               0 :     if (node->getQualifier() == EvqConst)
     399               0 :         return false;
     400                 : 
     401               0 :     error(node->getLine(), "constant expression required", "", "");
     402                 : 
     403               0 :     return true;
     404                 : }
     405                 : 
     406                 : //
     407                 : // Both test, and if necessary spit out an error, to see if the node is really
     408                 : // an integer.
     409                 : //
     410                 : // Returns true if the was an error.
     411                 : //
     412               0 : bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
     413                 : {
     414               0 :     if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
     415               0 :         return false;
     416                 : 
     417               0 :     error(node->getLine(), "integer expression required", token, "");
     418                 : 
     419               0 :     return true;
     420                 : }
     421                 : 
     422                 : //
     423                 : // Both test, and if necessary spit out an error, to see if we are currently
     424                 : // globally scoped.
     425                 : //
     426                 : // Returns true if the was an error.
     427                 : //
     428               0 : bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
     429                 : {
     430               0 :     if (global)
     431               0 :         return false;
     432                 : 
     433               0 :     error(line, "only allowed at global scope", token, "");
     434                 : 
     435               0 :     return true;
     436                 : }
     437                 : 
     438                 : //
     439                 : // For now, keep it simple:  if it starts "gl_", it's reserved, independent
     440                 : // of scope.  Except, if the symbol table is at the built-in push-level,
     441                 : // which is when we are parsing built-ins.
     442                 : // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
     443                 : // webgl shader.
     444                 : //
     445                 : // Returns true if there was an error.
     446                 : //
     447               0 : bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
     448                 : {
     449                 :     static const char* reservedErrMsg = "reserved built-in name";
     450               0 :     if (!symbolTable.atBuiltInLevel()) {
     451               0 :         if (identifier.compare(0, 3, "gl_") == 0) {
     452               0 :             error(line, reservedErrMsg, "gl_", "");
     453               0 :             return true;
     454                 :         }
     455               0 :         if (shaderSpec == SH_WEBGL_SPEC) {
     456               0 :             if (identifier.compare(0, 6, "webgl_") == 0) {
     457               0 :                 error(line, reservedErrMsg, "webgl_", "");
     458               0 :                 return true;
     459                 :             }
     460               0 :             if (identifier.compare(0, 7, "_webgl_") == 0) {
     461               0 :                 error(line, reservedErrMsg, "_webgl_", "");
     462               0 :                 return true;
     463                 :             }
     464                 :         }
     465               0 :         if (identifier.find("__") != TString::npos) {
     466                 :             //error(line, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
     467                 :             //return true;
     468               0 :             infoSink.info.message(EPrefixWarning, "Two consecutive underscores are reserved for future use.", line);
     469               0 :             return false;
     470                 :         }
     471                 :     }
     472                 : 
     473               0 :     return false;
     474                 : }
     475                 : 
     476                 : //
     477                 : // Make sure there is enough data provided to the constructor to build
     478                 : // something of the type of the constructor.  Also returns the type of
     479                 : // the constructor.
     480                 : //
     481                 : // Returns true if there was an error in construction.
     482                 : //
     483               0 : bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
     484                 : {
     485               0 :     *type = function.getReturnType();
     486                 : 
     487               0 :     bool constructingMatrix = false;
     488               0 :     switch(op) {
     489                 :     case EOpConstructMat2:
     490                 :     case EOpConstructMat3:
     491                 :     case EOpConstructMat4:
     492               0 :         constructingMatrix = true;
     493               0 :         break;
     494                 :     default: 
     495               0 :         break;
     496                 :     }
     497                 : 
     498                 :     //
     499                 :     // Note: It's okay to have too many components available, but not okay to have unused
     500                 :     // arguments.  'full' will go to true when enough args have been seen.  If we loop
     501                 :     // again, there is an extra argument, so 'overfull' will become true.
     502                 :     //
     503                 : 
     504               0 :     int size = 0;
     505               0 :     bool constType = true;
     506               0 :     bool full = false;
     507               0 :     bool overFull = false;
     508               0 :     bool matrixInMatrix = false;
     509               0 :     bool arrayArg = false;
     510               0 :     for (int i = 0; i < function.getParamCount(); ++i) {
     511               0 :         const TParameter& param = function.getParam(i);
     512               0 :         size += param.type->getObjectSize();
     513                 :         
     514               0 :         if (constructingMatrix && param.type->isMatrix())
     515               0 :             matrixInMatrix = true;
     516               0 :         if (full)
     517               0 :             overFull = true;
     518               0 :         if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
     519               0 :             full = true;
     520               0 :         if (param.type->getQualifier() != EvqConst)
     521               0 :             constType = false;
     522               0 :         if (param.type->isArray())
     523               0 :             arrayArg = true;
     524                 :     }
     525                 :     
     526               0 :     if (constType)
     527               0 :         type->setQualifier(EvqConst);
     528                 : 
     529               0 :     if (type->isArray() && type->getArraySize() != function.getParamCount()) {
     530               0 :         error(line, "array constructor needs one argument per array element", "constructor", "");
     531               0 :         return true;
     532                 :     }
     533                 : 
     534               0 :     if (arrayArg && op != EOpConstructStruct) {
     535               0 :         error(line, "constructing from a non-dereferenced array", "constructor", "");
     536               0 :         return true;
     537                 :     }
     538                 : 
     539               0 :     if (matrixInMatrix && !type->isArray()) {
     540               0 :         if (function.getParamCount() != 1) {
     541               0 :           error(line, "constructing matrix from matrix can only take one argument", "constructor", "");
     542               0 :           return true;
     543                 :         }
     544                 :     }
     545                 : 
     546               0 :     if (overFull) {
     547               0 :         error(line, "too many arguments", "constructor", "");
     548               0 :         return true;
     549                 :     }
     550                 :     
     551               0 :     if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->size()) != function.getParamCount()) {
     552               0 :         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
     553               0 :         return true;
     554                 :     }
     555                 : 
     556               0 :     if (!type->isMatrix() || !matrixInMatrix) {
     557               0 :         if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
     558               0 :             (op == EOpConstructStruct && size < type->getObjectSize())) {
     559               0 :             error(line, "not enough data provided for construction", "constructor", "");
     560               0 :             return true;
     561                 :         }
     562                 :     }
     563                 : 
     564               0 :     TIntermTyped *typed = node ? node->getAsTyped() : 0;
     565               0 :     if (typed == 0) {
     566               0 :         error(line, "constructor argument does not have a type", "constructor", "");
     567               0 :         return true;
     568                 :     }
     569               0 :     if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
     570               0 :         error(line, "cannot convert a sampler", "constructor", "");
     571               0 :         return true;
     572                 :     }
     573               0 :     if (typed->getBasicType() == EbtVoid) {
     574               0 :         error(line, "cannot convert a void", "constructor", "");
     575               0 :         return true;
     576                 :     }
     577                 : 
     578               0 :     return false;
     579                 : }
     580                 : 
     581                 : // This function checks to see if a void variable has been declared and raise an error message for such a case
     582                 : //
     583                 : // returns true in case of an error
     584                 : //
     585               0 : bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
     586                 : {
     587               0 :     if (pubType.type == EbtVoid) {
     588               0 :         error(line, "illegal use of type 'void'", identifier.c_str(), "");
     589               0 :         return true;
     590                 :     } 
     591                 : 
     592               0 :     return false;
     593                 : }
     594                 : 
     595                 : // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
     596                 : //
     597                 : // returns true in case of an error
     598                 : //
     599               0 : bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
     600                 : {
     601               0 :     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
     602               0 :         error(line, "boolean expression expected", "", "");
     603               0 :         return true;
     604                 :     } 
     605                 : 
     606               0 :     return false;
     607                 : }
     608                 : 
     609                 : // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
     610                 : //
     611                 : // returns true in case of an error
     612                 : //
     613               0 : bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
     614                 : {
     615               0 :     if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
     616               0 :         error(line, "boolean expression expected", "", "");
     617               0 :         return true;
     618                 :     } 
     619                 : 
     620               0 :     return false;
     621                 : }
     622                 : 
     623               0 : bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
     624                 : {
     625               0 :     if (pType.type == EbtStruct) {
     626               0 :         if (containsSampler(*pType.userDef)) {
     627               0 :             error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
     628                 :         
     629               0 :             return true;
     630                 :         }
     631                 :         
     632               0 :         return false;
     633               0 :     } else if (IsSampler(pType.type)) {
     634               0 :         error(line, reason, getBasicString(pType.type), "");
     635                 : 
     636               0 :         return true;
     637                 :     }
     638                 : 
     639               0 :     return false;
     640                 : }
     641                 : 
     642               0 : bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
     643                 : {
     644               0 :     if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
     645                 :         pType.type == EbtStruct) {
     646               0 :         error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
     647                 :         
     648               0 :         return true;
     649                 :     }
     650                 : 
     651               0 :     if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
     652               0 :         return true;
     653                 : 
     654               0 :     return false;
     655                 : }
     656                 : 
     657               0 : bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
     658                 : {
     659               0 :     if ((qualifier == EvqOut || qualifier == EvqInOut) && 
     660               0 :              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
     661               0 :         error(line, "samplers cannot be output parameters", type.getBasicString(), "");
     662               0 :         return true;
     663                 :     }
     664                 : 
     665               0 :     return false;
     666                 : }
     667                 : 
     668               0 : bool TParseContext::containsSampler(TType& type)
     669                 : {
     670               0 :     if (IsSampler(type.getBasicType()))
     671               0 :         return true;
     672                 : 
     673               0 :     if (type.getBasicType() == EbtStruct) {
     674               0 :         TTypeList& structure = *type.getStruct();
     675               0 :         for (unsigned int i = 0; i < structure.size(); ++i) {
     676               0 :             if (containsSampler(*structure[i].type))
     677               0 :                 return true;
     678                 :         }
     679                 :     }
     680                 : 
     681               0 :     return false;
     682                 : }
     683                 : 
     684                 : //
     685                 : // Do size checking for an array type's size.
     686                 : //
     687                 : // Returns true if there was an error.
     688                 : //
     689               0 : bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
     690                 : {
     691               0 :     TIntermConstantUnion* constant = expr->getAsConstantUnion();
     692               0 :     if (constant == 0 || constant->getBasicType() != EbtInt) {
     693               0 :         error(line, "array size must be a constant integer expression", "", "");
     694               0 :         return true;
     695                 :     }
     696                 : 
     697               0 :     size = constant->getUnionArrayPointer()->getIConst();
     698                 : 
     699               0 :     if (size <= 0) {
     700               0 :         error(line, "array size must be a positive integer", "", "");
     701               0 :         size = 1;
     702               0 :         return true;
     703                 :     }
     704                 : 
     705               0 :     return false;
     706                 : }
     707                 : 
     708                 : //
     709                 : // See if this qualifier can be an array.
     710                 : //
     711                 : // Returns true if there is an error.
     712                 : //
     713               0 : bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
     714                 : {
     715               0 :     if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
     716               0 :         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
     717               0 :         return true;
     718                 :     }
     719                 : 
     720               0 :     return false;
     721                 : }
     722                 : 
     723                 : //
     724                 : // See if this type can be an array.
     725                 : //
     726                 : // Returns true if there is an error.
     727                 : //
     728               0 : bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
     729                 : {
     730                 :     //
     731                 :     // Can the type be an array?
     732                 :     //
     733               0 :     if (type.array) {
     734               0 :         error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), "");
     735               0 :         return true;
     736                 :     }
     737                 : 
     738               0 :     return false;
     739                 : }
     740                 : 
     741                 : //
     742                 : // Do all the semantic checking for declaring an array, with and 
     743                 : // without a size, and make the right changes to the symbol table.
     744                 : //
     745                 : // size == 0 means no specified size.
     746                 : //
     747                 : // Returns true if there was an error.
     748                 : //
     749               0 : bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
     750                 : {
     751                 :     //
     752                 :     // Don't check for reserved word use until after we know it's not in the symbol table,
     753                 :     // because reserved arrays can be redeclared.
     754                 :     //
     755                 : 
     756               0 :     bool builtIn = false; 
     757               0 :     bool sameScope = false;
     758               0 :     TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
     759               0 :     if (symbol == 0 || !sameScope) {
     760               0 :         if (reservedErrorCheck(line, identifier))
     761               0 :             return true;
     762                 :         
     763               0 :         variable = new TVariable(&identifier, TType(type));
     764                 : 
     765               0 :         if (type.arraySize)
     766               0 :             variable->getType().setArraySize(type.arraySize);
     767                 : 
     768               0 :         if (! symbolTable.insert(*variable)) {
     769               0 :             delete variable;
     770               0 :             error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
     771               0 :             return true;
     772                 :         }
     773                 :     } else {
     774               0 :         if (! symbol->isVariable()) {
     775               0 :             error(line, "variable expected", identifier.c_str(), "");
     776               0 :             return true;
     777                 :         }
     778                 : 
     779               0 :         variable = static_cast<TVariable*>(symbol);
     780               0 :         if (! variable->getType().isArray()) {
     781               0 :             error(line, "redeclaring non-array as array", identifier.c_str(), "");
     782               0 :             return true;
     783                 :         }
     784               0 :         if (variable->getType().getArraySize() > 0) {
     785               0 :             error(line, "redeclaration of array with size", identifier.c_str(), "");
     786               0 :             return true;
     787                 :         }
     788                 :         
     789               0 :         if (! variable->getType().sameElementType(TType(type))) {
     790               0 :             error(line, "redeclaration of array with a different type", identifier.c_str(), "");
     791               0 :             return true;
     792                 :         }
     793                 : 
     794               0 :         TType* t = variable->getArrayInformationType();
     795               0 :         while (t != 0) {
     796               0 :             if (t->getMaxArraySize() > type.arraySize) {
     797               0 :                 error(line, "higher index value already used for the array", identifier.c_str(), "");
     798               0 :                 return true;
     799                 :             }
     800               0 :             t->setArraySize(type.arraySize);
     801               0 :             t = t->getArrayInformationType();
     802                 :         }
     803                 : 
     804               0 :         if (type.arraySize)
     805               0 :             variable->getType().setArraySize(type.arraySize);
     806                 :     } 
     807                 : 
     808               0 :     if (voidErrorCheck(line, identifier, type))
     809               0 :         return true;
     810                 : 
     811               0 :     return false;
     812                 : }
     813                 : 
     814               0 : bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
     815                 : {
     816               0 :     bool builtIn = false;
     817               0 :     TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
     818               0 :     if (symbol == 0) {
     819               0 :         error(line, " undeclared identifier", node->getSymbol().c_str(), "");
     820               0 :         return true;
     821                 :     }
     822               0 :     TVariable* variable = static_cast<TVariable*>(symbol);
     823                 : 
     824               0 :     type->setArrayInformationType(variable->getArrayInformationType());
     825               0 :     variable->updateArrayInformationType(type);
     826                 : 
     827                 :     // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
     828                 :     // its an error
     829               0 :     if (node->getSymbol() == "gl_FragData") {
     830               0 :         TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
     831               0 :         if (fragData == 0) {
     832               0 :             infoSink.info.message(EPrefixInternalError, "gl_MaxDrawBuffers not defined", line);
     833               0 :             return true;
     834                 :         }
     835                 : 
     836               0 :         int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
     837               0 :         if (fragDataValue <= size) {
     838               0 :             error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers", "");
     839               0 :             return true;
     840                 :         }
     841                 :     }
     842                 : 
     843                 :     // we dont want to update the maxArraySize when this flag is not set, we just want to include this 
     844                 :     // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
     845               0 :     if (!updateFlag)
     846               0 :         return false;
     847                 : 
     848               0 :     size++;
     849               0 :     variable->getType().setMaxArraySize(size);
     850               0 :     type->setMaxArraySize(size);
     851               0 :     TType* tt = type;
     852                 : 
     853               0 :     while(tt->getArrayInformationType() != 0) {
     854               0 :         tt = tt->getArrayInformationType();
     855               0 :         tt->setMaxArraySize(size);
     856                 :     }
     857                 : 
     858               0 :     return false;
     859                 : }
     860                 : 
     861                 : //
     862                 : // Enforce non-initializer type/qualifier rules.
     863                 : //
     864                 : // Returns true if there was an error.
     865                 : //
     866               0 : bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type)
     867                 : {
     868                 :     //
     869                 :     // Make the qualifier make sense.
     870                 :     //
     871               0 :     if (type.qualifier == EvqConst) {
     872               0 :         type.qualifier = EvqTemporary;
     873               0 :         error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
     874               0 :         return true;
     875                 :     }
     876                 : 
     877               0 :     return false;
     878                 : }
     879                 : 
     880                 : //
     881                 : // Do semantic checking for a variable declaration that has no initializer,
     882                 : // and update the symbol table.
     883                 : //
     884                 : // Returns true if there was an error.
     885                 : //
     886               0 : bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
     887                 : {
     888               0 :     if (reservedErrorCheck(line, identifier))
     889               0 :         recover();
     890                 : 
     891               0 :     variable = new TVariable(&identifier, TType(type));
     892                 : 
     893               0 :     if (! symbolTable.insert(*variable)) {
     894               0 :         error(line, "redefinition", variable->getName().c_str(), "");
     895               0 :         delete variable;
     896               0 :         variable = 0;
     897               0 :         return true;
     898                 :     }
     899                 : 
     900               0 :     if (voidErrorCheck(line, identifier, type))
     901               0 :         return true;
     902                 : 
     903               0 :     return false;
     904                 : }
     905                 : 
     906               0 : bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
     907                 : {    
     908               0 :     if (qualifier != EvqConst && qualifier != EvqTemporary) {
     909               0 :         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
     910               0 :         return true;
     911                 :     }
     912               0 :     if (qualifier == EvqConst && paramQualifier != EvqIn) {
     913               0 :         error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
     914               0 :         return true;
     915                 :     }
     916                 : 
     917               0 :     if (qualifier == EvqConst)
     918               0 :         type->setQualifier(EvqConstReadOnly);
     919                 :     else
     920               0 :         type->setQualifier(paramQualifier);
     921                 : 
     922               0 :     return false;
     923                 : }
     924                 : 
     925               0 : bool TParseContext::extensionErrorCheck(int line, const TString& extension)
     926                 : {
     927               0 :     TExtensionBehavior::const_iterator iter = extensionBehavior.find(extension);
     928               0 :     if (iter == extensionBehavior.end()) {
     929               0 :         error(line, "extension", extension.c_str(), "is not supported");
     930               0 :         return true;
     931                 :     }
     932                 :     // In GLSL ES, an extension's default behavior is "disable".
     933               0 :     if (iter->second == EBhDisable || iter->second == EBhUndefined) {
     934               0 :         error(line, "extension", extension.c_str(), "is disabled");
     935               0 :         return true;
     936                 :     }
     937               0 :     if (iter->second == EBhWarn) {
     938               0 :         TString msg = "extension " + extension + " is being used";
     939               0 :         infoSink.info.message(EPrefixWarning, msg.c_str(), line);
     940               0 :         return false;
     941                 :     }
     942                 : 
     943               0 :     return false;
     944                 : }
     945                 : 
     946               0 : bool TParseContext::supportsExtension(const char* extension)
     947                 : {
     948               0 :     TExtensionBehavior::const_iterator iter = extensionBehavior.find(extension);
     949               0 :     return (iter != extensionBehavior.end());
     950                 : }
     951                 : 
     952                 : /////////////////////////////////////////////////////////////////////////////////
     953                 : //
     954                 : // Non-Errors.
     955                 : //
     956                 : /////////////////////////////////////////////////////////////////////////////////
     957                 : 
     958                 : //
     959                 : // Look up a function name in the symbol table, and make sure it is a function.
     960                 : //
     961                 : // Return the function symbol if found, otherwise 0.
     962                 : //
     963               0 : const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
     964                 : {
     965                 :     // First find by unmangled name to check whether the function name has been
     966                 :     // hidden by a variable name or struct typename.
     967               0 :     const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
     968               0 :     if (symbol == 0) {
     969               0 :         symbol = symbolTable.find(call->getMangledName(), builtIn);
     970                 :     }
     971                 : 
     972               0 :     if (symbol == 0) {
     973               0 :         error(line, "no matching overloaded function found", call->getName().c_str(), "");
     974               0 :         return 0;
     975                 :     }
     976                 : 
     977               0 :     if (!symbol->isFunction()) {
     978               0 :         error(line, "function name expected", call->getName().c_str(), "");
     979               0 :         return 0;
     980                 :     }
     981                 : 
     982               0 :     return static_cast<const TFunction*>(symbol);
     983                 : }
     984                 : 
     985                 : //
     986                 : // Initializers show up in several places in the grammar.  Have one set of
     987                 : // code to handle them here.
     988                 : //
     989               0 : bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, 
     990                 :                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
     991                 : {
     992               0 :     TType type = TType(pType);
     993                 : 
     994               0 :     if (variable == 0) {
     995               0 :         if (reservedErrorCheck(line, identifier))
     996               0 :             return true;
     997                 : 
     998               0 :         if (voidErrorCheck(line, identifier, pType))
     999               0 :             return true;
    1000                 : 
    1001                 :         //
    1002                 :         // add variable to symbol table
    1003                 :         //
    1004               0 :         variable = new TVariable(&identifier, type);
    1005               0 :         if (! symbolTable.insert(*variable)) {
    1006               0 :             error(line, "redefinition", variable->getName().c_str(), "");
    1007               0 :             return true;
    1008                 :             // don't delete variable, it's used by error recovery, and the pool 
    1009                 :             // pop will take care of the memory
    1010                 :         }
    1011                 :     }
    1012                 : 
    1013                 :     //
    1014                 :     // identifier must be of type constant, a global, or a temporary
    1015                 :     //
    1016               0 :     TQualifier qualifier = variable->getType().getQualifier();
    1017               0 :     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
    1018               0 :         error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
    1019               0 :         return true;
    1020                 :     }
    1021                 :     //
    1022                 :     // test for and propagate constant
    1023                 :     //
    1024                 : 
    1025               0 :     if (qualifier == EvqConst) {
    1026               0 :         if (qualifier != initializer->getType().getQualifier()) {
    1027               0 :             error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
    1028               0 :             variable->getType().setQualifier(EvqTemporary);
    1029               0 :             return true;
    1030                 :         }
    1031               0 :         if (type != initializer->getType()) {
    1032                 :             error(line, " non-matching types for const initializer ", 
    1033               0 :                 variable->getType().getQualifierString(), "");
    1034               0 :             variable->getType().setQualifier(EvqTemporary);
    1035               0 :             return true;
    1036                 :         }
    1037               0 :         if (initializer->getAsConstantUnion()) { 
    1038               0 :             ConstantUnion* unionArray = variable->getConstPointer();
    1039                 : 
    1040               0 :             if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
    1041               0 :                 *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
    1042                 :             } else {
    1043               0 :                 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
    1044                 :             }
    1045               0 :         } else if (initializer->getAsSymbolNode()) {
    1046               0 :             const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
    1047               0 :             const TVariable* tVar = static_cast<const TVariable*>(symbol);
    1048                 : 
    1049               0 :             ConstantUnion* constArray = tVar->getConstPointer();
    1050               0 :             variable->shareConstPointer(constArray);
    1051                 :         } else {
    1052               0 :             error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
    1053               0 :             variable->getType().setQualifier(EvqTemporary);
    1054               0 :             return true;
    1055                 :         }
    1056                 :     }
    1057                 :  
    1058               0 :     if (qualifier != EvqConst) {
    1059               0 :         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
    1060               0 :         intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
    1061               0 :         if (intermNode == 0) {
    1062               0 :             assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
    1063               0 :             return true;
    1064                 :         }
    1065                 :     } else 
    1066               0 :         intermNode = 0;
    1067                 : 
    1068               0 :     return false;
    1069                 : }
    1070                 : 
    1071               0 : bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
    1072                 : {
    1073               0 :     ASSERT(aggrNode != NULL);
    1074               0 :     if (!aggrNode->isConstructor())
    1075               0 :         return false;
    1076                 : 
    1077               0 :     bool allConstant = true;
    1078                 : 
    1079                 :     // check if all the child nodes are constants so that they can be inserted into 
    1080                 :     // the parent node
    1081               0 :     TIntermSequence &sequence = aggrNode->getSequence() ;
    1082               0 :     for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
    1083               0 :         if (!(*p)->getAsTyped()->getAsConstantUnion())
    1084               0 :             return false;
    1085                 :     }
    1086                 : 
    1087               0 :     return allConstant;
    1088                 : }
    1089                 : 
    1090                 : // This function is used to test for the correctness of the parameters passed to various constructor functions
    1091                 : // and also convert them to the right datatype if it is allowed and required. 
    1092                 : //
    1093                 : // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
    1094                 : //
    1095               0 : TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
    1096                 : {
    1097               0 :     if (node == 0)
    1098               0 :         return 0;
    1099                 : 
    1100               0 :     TIntermAggregate* aggrNode = node->getAsAggregate();
    1101                 :     
    1102               0 :     TTypeList::const_iterator memberTypes;
    1103               0 :     if (op == EOpConstructStruct)
    1104               0 :         memberTypes = type->getStruct()->begin();
    1105                 :     
    1106               0 :     TType elementType = *type;
    1107               0 :     if (type->isArray())
    1108               0 :         elementType.clearArrayness();
    1109                 : 
    1110                 :     bool singleArg;
    1111               0 :     if (aggrNode) {
    1112               0 :         if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
    1113               0 :             singleArg = true;
    1114                 :         else
    1115               0 :             singleArg = false;
    1116                 :     } else
    1117               0 :         singleArg = true;
    1118                 : 
    1119                 :     TIntermTyped *newNode;
    1120               0 :     if (singleArg) {
    1121                 :         // If structure constructor or array constructor is being called 
    1122                 :         // for only one parameter inside the structure, we need to call constructStruct function once.
    1123               0 :         if (type->isArray())
    1124               0 :             newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
    1125               0 :         else if (op == EOpConstructStruct)
    1126               0 :             newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
    1127                 :         else
    1128               0 :             newNode = constructBuiltIn(type, op, node, node->getLine(), false);
    1129                 : 
    1130               0 :         if (newNode && newNode->getAsAggregate()) {
    1131               0 :             TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
    1132               0 :             if (constConstructor)
    1133               0 :                 return constConstructor;
    1134                 :         }
    1135                 : 
    1136               0 :         return newNode;
    1137                 :     }
    1138                 :     
    1139                 :     //
    1140                 :     // Handle list of arguments.
    1141                 :     //
    1142               0 :     TIntermSequence &sequenceVector = aggrNode->getSequence() ;    // Stores the information about the parameter to the constructor
    1143                 :     // if the structure constructor contains more than one parameter, then construct
    1144                 :     // each parameter
    1145                 :     
    1146               0 :     int paramCount = 0;  // keeps a track of the constructor parameter number being checked    
    1147                 :     
    1148                 :     // for each parameter to the constructor call, check to see if the right type is passed or convert them 
    1149                 :     // to the right type if possible (and allowed).
    1150                 :     // for structure constructors, just check if the right type is passed, no conversion is allowed.
    1151                 :     
    1152               0 :     for (TIntermSequence::iterator p = sequenceVector.begin(); 
    1153               0 :                                    p != sequenceVector.end(); p++, paramCount++) {
    1154               0 :         if (type->isArray())
    1155               0 :             newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
    1156               0 :         else if (op == EOpConstructStruct)
    1157               0 :             newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
    1158                 :         else
    1159               0 :             newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
    1160                 :         
    1161               0 :         if (newNode) {
    1162               0 :             *p = newNode;
    1163                 :         }
    1164                 :     }
    1165                 : 
    1166               0 :     TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
    1167               0 :     TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
    1168               0 :     if (constConstructor)
    1169               0 :         return constConstructor;
    1170                 : 
    1171               0 :     return constructor;
    1172                 : }
    1173                 : 
    1174               0 : TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
    1175                 : {
    1176               0 :     bool canBeFolded = areAllChildConst(aggrNode);
    1177               0 :     aggrNode->setType(type);
    1178               0 :     if (canBeFolded) {
    1179               0 :         bool returnVal = false;
    1180               0 :         ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
    1181               0 :         if (aggrNode->getSequence().size() == 1)  {
    1182               0 :             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type, true);
    1183                 :         }
    1184                 :         else {
    1185               0 :             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable,  type);
    1186                 :         }
    1187               0 :         if (returnVal)
    1188               0 :             return 0;
    1189                 : 
    1190               0 :         return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
    1191                 :     }
    1192                 : 
    1193               0 :     return 0;
    1194                 : }
    1195                 : 
    1196                 : // Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
    1197                 : // for the parameter to the constructor (passed to this function). Essentially, it converts
    1198                 : // the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a 
    1199                 : // float, then float is converted to int.
    1200                 : //
    1201                 : // Returns 0 for an error or the constructed node.
    1202                 : //
    1203               0 : TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
    1204                 : {
    1205                 :     TIntermTyped* newNode;
    1206                 :     TOperator basicOp;
    1207                 : 
    1208                 :     //
    1209                 :     // First, convert types as needed.
    1210                 :     //
    1211               0 :     switch (op) {
    1212                 :     case EOpConstructVec2:
    1213                 :     case EOpConstructVec3:
    1214                 :     case EOpConstructVec4:
    1215                 :     case EOpConstructMat2:
    1216                 :     case EOpConstructMat3:
    1217                 :     case EOpConstructMat4:
    1218                 :     case EOpConstructFloat:
    1219               0 :         basicOp = EOpConstructFloat;
    1220               0 :         break;
    1221                 : 
    1222                 :     case EOpConstructIVec2:
    1223                 :     case EOpConstructIVec3:
    1224                 :     case EOpConstructIVec4:
    1225                 :     case EOpConstructInt:
    1226               0 :         basicOp = EOpConstructInt;
    1227               0 :         break;
    1228                 : 
    1229                 :     case EOpConstructBVec2:
    1230                 :     case EOpConstructBVec3:
    1231                 :     case EOpConstructBVec4:
    1232                 :     case EOpConstructBool:
    1233               0 :         basicOp = EOpConstructBool;
    1234               0 :         break;
    1235                 : 
    1236                 :     default:
    1237               0 :         error(line, "unsupported construction", "", "");
    1238               0 :         recover();
    1239                 : 
    1240               0 :         return 0;
    1241                 :     }
    1242               0 :     newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
    1243               0 :     if (newNode == 0) {
    1244               0 :         error(line, "can't convert", "constructor", "");
    1245               0 :         return 0;
    1246                 :     }
    1247                 : 
    1248                 :     //
    1249                 :     // Now, if there still isn't an operation to do the construction, and we need one, add one.
    1250                 :     //
    1251                 :     
    1252                 :     // Otherwise, skip out early.
    1253               0 :     if (subset || (newNode != node && newNode->getType() == *type))
    1254               0 :         return newNode;
    1255                 : 
    1256                 :     // setAggregateOperator will insert a new node for the constructor, as needed.
    1257               0 :     return intermediate.setAggregateOperator(newNode, op, line);
    1258                 : }
    1259                 : 
    1260                 : // This function tests for the type of the parameters to the structures constructors. Raises
    1261                 : // an error message if the expected type does not match the parameter passed to the constructor.
    1262                 : //
    1263                 : // Returns 0 for an error or the input node itself if the expected and the given parameter types match.
    1264                 : //
    1265               0 : TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
    1266                 : {
    1267               0 :     if (*type == node->getAsTyped()->getType()) {
    1268               0 :         if (subset)
    1269               0 :             return node->getAsTyped();
    1270                 :         else
    1271               0 :             return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
    1272                 :     } else {
    1273                 :         error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
    1274               0 :                 node->getAsTyped()->getType().getBasicString(), type->getBasicString());
    1275               0 :         recover();
    1276                 :     }
    1277                 : 
    1278               0 :     return 0;
    1279                 : }
    1280                 : 
    1281                 : //
    1282                 : // This function returns the tree representation for the vector field(s) being accessed from contant vector.
    1283                 : // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
    1284                 : // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
    1285                 : // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
    1286                 : // a constant matrix.
    1287                 : //
    1288               0 : TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
    1289                 : {
    1290                 :     TIntermTyped* typedNode;
    1291               0 :     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
    1292                 : 
    1293                 :     ConstantUnion *unionArray;
    1294               0 :     if (tempConstantNode) {
    1295               0 :         unionArray = tempConstantNode->getUnionArrayPointer();
    1296                 : 
    1297               0 :         if (!unionArray) {  // this error message should never be raised
    1298               0 :             infoSink.info.message(EPrefixInternalError, "ConstantUnion not initialized in addConstVectorNode function", line);
    1299               0 :             recover();
    1300                 : 
    1301               0 :             return node;
    1302                 :         }
    1303                 :     } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
    1304               0 :         error(line, "Cannot offset into the vector", "Error", "");
    1305               0 :         recover();
    1306                 : 
    1307               0 :         return 0;
    1308                 :     }
    1309                 : 
    1310               0 :     ConstantUnion* constArray = new ConstantUnion[fields.num];
    1311                 : 
    1312               0 :     for (int i = 0; i < fields.num; i++) {
    1313               0 :         if (fields.offsets[i] >= node->getType().getObjectSize()) {
    1314               0 :             error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
    1315               0 :             recover();
    1316               0 :             fields.offsets[i] = 0;
    1317                 :         }
    1318                 :         
    1319               0 :         constArray[i] = unionArray[fields.offsets[i]];
    1320                 : 
    1321                 :     } 
    1322               0 :     typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
    1323               0 :     return typedNode;
    1324                 : }
    1325                 : 
    1326                 : //
    1327                 : // This function returns the column being accessed from a constant matrix. The values are retrieved from
    1328                 : // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input 
    1329                 : // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a 
    1330                 : // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
    1331                 : //
    1332               0 : TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
    1333                 : {
    1334                 :     TIntermTyped* typedNode;
    1335               0 :     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
    1336                 : 
    1337               0 :     if (index >= node->getType().getNominalSize()) {
    1338               0 :         error(line, "", "[", "matrix field selection out of range '%d'", index);
    1339               0 :         recover();
    1340               0 :         index = 0;
    1341                 :     }
    1342                 : 
    1343               0 :     if (tempConstantNode) {
    1344               0 :          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
    1345               0 :          int size = tempConstantNode->getType().getNominalSize();
    1346               0 :          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
    1347                 :     } else {
    1348               0 :         error(line, "Cannot offset into the matrix", "Error", "");
    1349               0 :         recover();
    1350                 : 
    1351               0 :         return 0;
    1352                 :     }
    1353                 : 
    1354               0 :     return typedNode;
    1355                 : }
    1356                 : 
    1357                 : 
    1358                 : //
    1359                 : // This function returns an element of an array accessed from a constant array. The values are retrieved from
    1360                 : // the symbol table and parse-tree is built for the type of the element. The input 
    1361                 : // to the function could either be a symbol node (a[0] where a is a constant array)that represents a 
    1362                 : // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
    1363                 : //
    1364               0 : TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
    1365                 : {
    1366                 :     TIntermTyped* typedNode;
    1367               0 :     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
    1368               0 :     TType arrayElementType = node->getType();
    1369               0 :     arrayElementType.clearArrayness();
    1370                 : 
    1371               0 :     if (index >= node->getType().getArraySize()) {
    1372               0 :         error(line, "", "[", "array field selection out of range '%d'", index);
    1373               0 :         recover();
    1374               0 :         index = 0;
    1375                 :     }
    1376                 : 
    1377               0 :     int arrayElementSize = arrayElementType.getObjectSize();
    1378                 : 
    1379               0 :     if (tempConstantNode) {
    1380               0 :          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
    1381               0 :          typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
    1382                 :     } else {
    1383               0 :         error(line, "Cannot offset into the array", "Error", "");
    1384               0 :         recover();
    1385                 : 
    1386               0 :         return 0;
    1387                 :     }
    1388                 : 
    1389               0 :     return typedNode;
    1390                 : }
    1391                 : 
    1392                 : 
    1393                 : //
    1394                 : // This function returns the value of a particular field inside a constant structure from the symbol table. 
    1395                 : // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
    1396                 : // function and returns the parse-tree with the values of the embedded/nested struct.
    1397                 : //
    1398               0 : TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
    1399                 : {
    1400               0 :     const TTypeList* fields = node->getType().getStruct();
    1401                 :     TIntermTyped *typedNode;
    1402               0 :     int instanceSize = 0;
    1403               0 :     unsigned int index = 0;
    1404               0 :     TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
    1405                 : 
    1406               0 :     for ( index = 0; index < fields->size(); ++index) {
    1407               0 :         if ((*fields)[index].type->getFieldName() == identifier) {
    1408               0 :             break;
    1409                 :         } else {
    1410               0 :             instanceSize += (*fields)[index].type->getObjectSize();
    1411                 :         }
    1412                 :     }
    1413                 : 
    1414               0 :     if (tempConstantNode) {
    1415               0 :          ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
    1416                 : 
    1417               0 :          typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
    1418                 :     } else {
    1419               0 :         error(line, "Cannot offset into the structure", "Error", "");
    1420               0 :         recover();
    1421                 : 
    1422               0 :         return 0;
    1423                 :     }
    1424                 : 
    1425               0 :     return typedNode;
    1426                 : }
    1427                 : 
    1428               0 : bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
    1429                 : {
    1430               0 :     ++structNestingLevel;
    1431                 : 
    1432                 :     // Embedded structure definitions are not supported per GLSL ES spec.
    1433                 :     // They aren't allowed in GLSL either, but we need to detect this here
    1434                 :     // so we don't rely on the GLSL compiler to catch it.
    1435               0 :     if (structNestingLevel > 1) {
    1436               0 :         error(line, "", "Embedded struct definitions are not allowed", "");
    1437               0 :         return true;
    1438                 :     }
    1439                 : 
    1440               0 :     return false;
    1441                 : }
    1442                 : 
    1443               0 : void TParseContext::exitStructDeclaration()
    1444                 : {
    1445               0 :     --structNestingLevel;
    1446               0 : }
    1447                 : 
    1448                 : namespace {
    1449                 : 
    1450                 : const int kWebGLMaxStructNesting = 4;
    1451                 : 
    1452                 : }  // namespace
    1453                 : 
    1454               0 : bool TParseContext::structNestingErrorCheck(TSourceLoc line, const TType& fieldType)
    1455                 : {
    1456               0 :     if (shaderSpec != SH_WEBGL_SPEC) {
    1457               0 :         return false;
    1458                 :     }
    1459                 : 
    1460               0 :     if (fieldType.getBasicType() != EbtStruct) {
    1461               0 :         return false;
    1462                 :     }
    1463                 : 
    1464                 :     // We're already inside a structure definition at this point, so add
    1465                 :     // one to the field's struct nesting.
    1466               0 :     if (1 + fieldType.getDeepestStructNesting() > kWebGLMaxStructNesting) {
    1467                 :         error(line, "", "", "Reference of struct type %s exceeds maximum struct nesting of %d",
    1468               0 :               fieldType.getTypeName().c_str(), kWebGLMaxStructNesting);
    1469               0 :         return true;
    1470                 :     }
    1471                 : 
    1472               0 :     return false;
    1473                 : }
    1474                 : 
    1475                 : //
    1476                 : // Parse an array of strings using yyparse.
    1477                 : //
    1478                 : // Returns 0 for success.
    1479                 : //
    1480               0 : int PaParseStrings(int count, const char* const string[], const int length[],
    1481                 :                    TParseContext* context) {
    1482               0 :     if ((count == 0) || (string == NULL))
    1483               0 :         return 1;
    1484                 : 
    1485                 :     // setup preprocessor.
    1486               0 :     if (InitPreprocessor())
    1487               0 :         return 1;
    1488               0 :     DefineExtensionMacros(context->extensionBehavior);
    1489                 : 
    1490               0 :     if (glslang_initialize(context))
    1491               0 :         return 1;
    1492                 : 
    1493               0 :     glslang_scan(count, string, length, context);
    1494               0 :     int error = glslang_parse(context);
    1495                 : 
    1496               0 :     glslang_finalize(context);
    1497               0 :     FinalizePreprocessor();
    1498               0 :     return (error == 0) && (context->numErrors == 0) ? 0 : 1;
    1499                 : }
    1500                 : 
    1501                 : OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
    1502                 : 
    1503               0 : bool InitializeParseContextIndex()
    1504                 : {
    1505               0 :     if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
    1506               0 :         assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
    1507                 :         return false;
    1508                 :     }
    1509                 : 
    1510                 :     //
    1511                 :     // Allocate a TLS index.
    1512                 :     //
    1513               0 :     GlobalParseContextIndex = OS_AllocTLSIndex();
    1514                 :     
    1515               0 :     if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
    1516               0 :         assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
    1517                 :         return false;
    1518                 :     }
    1519                 : 
    1520               0 :     return true;
    1521                 : }
    1522                 : 
    1523               0 : bool FreeParseContextIndex()
    1524                 : {
    1525               0 :     OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
    1526                 : 
    1527               0 :     if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
    1528               0 :         assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
    1529                 :         return false;
    1530                 :     }
    1531                 : 
    1532               0 :     GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
    1533                 : 
    1534               0 :     return OS_FreeTLSIndex(tlsiIndex);
    1535                 : }
    1536                 : 
    1537               0 : bool InitializeGlobalParseContext()
    1538                 : {
    1539               0 :     if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
    1540               0 :         assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
    1541                 :         return false;
    1542                 :     }
    1543                 : 
    1544               0 :     TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
    1545               0 :     if (lpParseContext != 0) {
    1546               0 :         assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
    1547                 :         return false;
    1548                 :     }
    1549                 : 
    1550               0 :     TThreadParseContext *lpThreadData = new TThreadParseContext();
    1551               0 :     if (lpThreadData == 0) {
    1552               0 :         assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
    1553                 :         return false;
    1554                 :     }
    1555                 : 
    1556               0 :     lpThreadData->lpGlobalParseContext = 0;
    1557               0 :     OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
    1558                 : 
    1559               0 :     return true;
    1560                 : }
    1561                 : 
    1562               0 : bool FreeParseContext()
    1563                 : {
    1564               0 :     if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
    1565               0 :         assert(0 && "FreeParseContext(): Parse Context index not initalised");
    1566                 :         return false;
    1567                 :     }
    1568                 : 
    1569               0 :     TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
    1570               0 :     if (lpParseContext)
    1571                 :         delete lpParseContext;
    1572                 : 
    1573               0 :     return true;
    1574                 : }
    1575                 : 
    1576               0 : TParseContextPointer& GetGlobalParseContext()
    1577                 : {
    1578                 :     //
    1579                 :     // Minimal error checking for speed
    1580                 :     //
    1581                 : 
    1582               0 :     TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
    1583                 : 
    1584               0 :     return lpParseContext->lpGlobalParseContext;
    1585                 : }
    1586                 : 

Generated by: LCOV version 1.7