OSDN Git Service

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