OSDN Git Service

Initializer cleanup
[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 TBasicType& type)
560 {
561     if(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 // These checks are common for all declarations starting a declarator list, and declarators that follow an empty
658 // declaration.
659 //
660 bool TParseContext::singleDeclarationErrorCheck(const TPublicType &publicType, const TSourceLoc &identifierLocation)
661 {
662         switch(publicType.qualifier)
663         {
664         case EvqVaryingIn:
665         case EvqVaryingOut:
666         case EvqAttribute:
667         case EvqVertexIn:
668         case EvqFragmentOut:
669                 if(publicType.type == EbtStruct)
670                 {
671                         error(identifierLocation, "cannot be used with a structure",
672                                 getQualifierString(publicType.qualifier));
673                         return true;
674                 }
675
676         default: break;
677         }
678
679         if(publicType.qualifier != EvqUniform && samplerErrorCheck(identifierLocation, publicType,
680                 "samplers must be uniform"))
681         {
682                 return true;
683         }
684
685         // check for layout qualifier issues
686         const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
687
688         if(layoutQualifier.matrixPacking != EmpUnspecified)
689         {
690                 error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking),
691                         "only valid for interface blocks");
692                 return true;
693         }
694
695         if(layoutQualifier.blockStorage != EbsUnspecified)
696         {
697                 error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage),
698                         "only valid for interface blocks");
699                 return true;
700         }
701
702         if(publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut &&
703                 layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier))
704         {
705                 return true;
706         }
707
708         return false;
709 }
710
711 bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier)\r
712 {\r
713         if(layoutQualifier.location != -1)\r
714         {\r
715                 error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");\r
716                 return true;\r
717         }\r
718 \r
719         return false;\r
720 }\r
721
722 bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType)
723 {
724         if(pType.layoutQualifier.location != -1)
725         {
726                 error(line, "location must only be specified for a single input or output variable", "location");
727                 return true;
728         }
729
730         return false;
731 }
732
733 bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
734 {
735     if ((qualifier == EvqOut || qualifier == EvqInOut) &&
736              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
737         error(line, "samplers cannot be output parameters", type.getBasicString());
738         return true;
739     }
740
741     return false;
742 }
743
744 bool TParseContext::containsSampler(TType& type)
745 {
746     if (IsSampler(type.getBasicType()))
747         return true;
748
749     if (type.getBasicType() == EbtStruct) {
750         const TFieldList& fields = type.getStruct()->fields();
751         for(unsigned int i = 0; i < fields.size(); ++i) {
752             if (containsSampler(*fields[i]->type()))
753                 return true;
754         }
755     }
756
757     return false;
758 }
759
760 //
761 // Do size checking for an array type's size.
762 //
763 // Returns true if there was an error.
764 //
765 bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
766 {
767     TIntermConstantUnion* constant = expr->getAsConstantUnion();
768
769     if (constant == 0 || !constant->isScalarInt())
770     {
771         error(line, "array size must be a constant integer expression", "");
772         return true;
773     }
774
775     if (constant->getBasicType() == EbtUInt)
776     {
777         unsigned int uintSize = constant->getUConst(0);
778         if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max()))
779         {
780             error(line, "array size too large", "");
781             size = 1;
782             return true;
783         }
784
785         size = static_cast<int>(uintSize);
786     }
787     else
788     {
789         size = constant->getIConst(0);
790
791         if (size <= 0)
792         {
793             error(line, "array size must be a positive integer", "");
794             size = 1;
795             return true;
796         }
797     }
798
799     return false;
800 }
801
802 //
803 // See if this qualifier can be an array.
804 //
805 // Returns true if there is an error.
806 //
807 bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
808 {
809     if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr)) {
810         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
811         return true;
812     }
813
814     return false;
815 }
816
817 //
818 // See if this type can be an array.
819 //
820 // Returns true if there is an error.
821 //
822 bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
823 {
824     //
825     // Can the type be an array?
826     //
827     if (type.array) {
828         error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
829         return true;
830     }
831
832     return false;
833 }
834
835 //
836 // Do all the semantic checking for declaring an array, with and
837 // without a size, and make the right changes to the symbol table.
838 //
839 // size == 0 means no specified size.
840 //
841 // Returns true if there was an error.
842 //
843 bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
844 {
845     //
846     // Don't check for reserved word use until after we know it's not in the symbol table,
847     // because reserved arrays can be redeclared.
848     //
849
850     bool builtIn = false;
851     bool sameScope = false;
852     TSymbol* symbol = symbolTable.find(identifier, shaderVersion, &builtIn, &sameScope);
853     if (symbol == 0 || !sameScope) {
854         if (reservedErrorCheck(line, identifier))
855             return true;
856
857         variable = new TVariable(&identifier, TType(type));
858
859         if (type.arraySize)
860             variable->getType().setArraySize(type.arraySize);
861
862         if (! symbolTable.declare(*variable)) {
863             delete variable;
864             error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
865             return true;
866         }
867     } else {
868         if (! symbol->isVariable()) {
869             error(line, "variable expected", identifier.c_str());
870             return true;
871         }
872
873         variable = static_cast<TVariable*>(symbol);
874         if (! variable->getType().isArray()) {
875             error(line, "redeclaring non-array as array", identifier.c_str());
876             return true;
877         }
878         if (variable->getType().getArraySize() > 0) {
879             error(line, "redeclaration of array with size", identifier.c_str());
880             return true;
881         }
882
883         if (! variable->getType().sameElementType(TType(type))) {
884             error(line, "redeclaration of array with a different type", identifier.c_str());
885             return true;
886         }
887
888         TType* t = variable->getArrayInformationType();
889         while (t != 0) {
890             if (t->getMaxArraySize() > type.arraySize) {
891                 error(line, "higher index value already used for the array", identifier.c_str());
892                 return true;
893             }
894             t->setArraySize(type.arraySize);
895             t = t->getArrayInformationType();
896         }
897
898         if (type.arraySize)
899             variable->getType().setArraySize(type.arraySize);
900     }
901
902     if (voidErrorCheck(line, identifier, type.type))
903         return true;
904
905     return false;
906 }
907
908 bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
909 {
910     bool builtIn = false;
911     TSymbol* symbol = symbolTable.find(node->getSymbol(), shaderVersion, &builtIn);
912     if (symbol == 0) {
913         error(line, " undeclared identifier", node->getSymbol().c_str());
914         return true;
915     }
916     TVariable* variable = static_cast<TVariable*>(symbol);
917
918     type->setArrayInformationType(variable->getArrayInformationType());
919     variable->updateArrayInformationType(type);
920
921     // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
922     // its an error
923     if (node->getSymbol() == "gl_FragData") {
924         TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", shaderVersion, &builtIn);
925         ASSERT(fragData);
926
927         int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
928         if (fragDataValue <= size) {
929             error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
930             return true;
931         }
932     }
933
934     // we dont want to update the maxArraySize when this flag is not set, we just want to include this
935     // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
936     if (!updateFlag)
937         return false;
938
939     size++;
940     variable->getType().setMaxArraySize(size);
941     type->setMaxArraySize(size);
942     TType* tt = type;
943
944     while(tt->getArrayInformationType() != 0) {
945         tt = tt->getArrayInformationType();
946         tt->setMaxArraySize(size);
947     }
948
949     return false;
950 }
951
952 //
953 // Enforce non-initializer type/qualifier rules.
954 //
955 // Returns true if there was an error.
956 //
957 bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
958 {
959     if (type.qualifier == EvqConstExpr)
960     {
961         // Make the qualifier make sense.
962         type.qualifier = EvqTemporary;
963
964         if (array)
965         {
966             error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
967         }
968         else if (type.isStructureContainingArrays())
969         {
970             error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
971         }
972         else
973         {
974             error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
975         }
976
977         return true;
978     }
979
980     return false;
981 }
982
983 //
984 // Do semantic checking for a variable declaration that has no initializer,
985 // and update the symbol table.
986 //
987 // Returns true if there was an error.
988 //
989 bool TParseContext::nonInitErrorCheck(int line, const TString& identifier, TPublicType& type)
990 {
991         if(type.qualifier == EvqConstExpr)
992         {
993                 // Make the qualifier make sense.
994                 type.qualifier = EvqTemporary;
995
996                 // Generate informative error messages for ESSL1.
997                 // In ESSL3 arrays and structures containing arrays can be constant.
998                 if(shaderVersion < 300 && type.isStructureContainingArrays())
999                 {
1000                         error(line,
1001                                 "structures containing arrays may not be declared constant since they cannot be initialized",
1002                                 identifier.c_str());
1003                 }
1004                 else
1005                 {
1006                         error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
1007                 }
1008
1009                 return true;
1010         }
1011         if(type.isUnsizedArray())
1012         {
1013                 error(line, "implicitly sized arrays need to be initialized", identifier.c_str());
1014                 return true;
1015         }
1016         return false;
1017 }
1018
1019 // Do some simple checks that are shared between all variable declarations,
1020 // and update the symbol table.
1021 //
1022 // Returns true if declaring the variable succeeded.
1023 //
1024 bool TParseContext::declareVariable(const TSourceLoc &line, const TString &identifier, const TType &type,
1025         TVariable **variable)
1026 {
1027         ASSERT((*variable) == nullptr);
1028
1029         // gl_LastFragData may be redeclared with a new precision qualifier
1030         if(type.isArray() && identifier.compare(0, 15, "gl_LastFragData") == 0)
1031         {
1032                 const TVariable *maxDrawBuffers =
1033                         static_cast<const TVariable *>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion));
1034                 if(type.getArraySize() != maxDrawBuffers->getConstPointer()->getIConst())
1035                 {
1036                         error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers", identifier.c_str());
1037                         return false;
1038                 }
1039         }
1040
1041         if(reservedErrorCheck(line, identifier))
1042                 return false;
1043
1044         (*variable) = new TVariable(&identifier, type);
1045         if(!symbolTable.declare(**variable))
1046         {
1047                 error(line, "redefinition", identifier.c_str());
1048                 delete (*variable);
1049                 (*variable) = nullptr;
1050                 return false;
1051         }
1052
1053         if(voidErrorCheck(line, identifier, type.getBasicType()))
1054                 return false;
1055
1056         return true;
1057 }
1058
1059 bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
1060 {
1061     if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) {
1062         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
1063         return true;
1064     }
1065     if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) {
1066         error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
1067         return true;
1068     }
1069
1070     if (qualifier == EvqConstReadOnly)
1071         type->setQualifier(EvqConstReadOnly);
1072     else
1073         type->setQualifier(paramQualifier);
1074
1075     return false;
1076 }
1077
1078 bool TParseContext::extensionErrorCheck(int line, const TString& extension)
1079 {
1080     const TExtensionBehavior& extBehavior = extensionBehavior();
1081     TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
1082     if (iter == extBehavior.end()) {
1083         error(line, "extension", extension.c_str(), "is not supported");
1084         return true;
1085     }
1086     // In GLSL ES, an extension's default behavior is "disable".
1087     if (iter->second == EBhDisable || iter->second == EBhUndefined) {
1088         error(line, "extension", extension.c_str(), "is disabled");
1089         return true;
1090     }
1091     if (iter->second == EBhWarn) {
1092         warning(line, "extension", extension.c_str(), "is being used");
1093         return false;
1094     }
1095
1096     return false;
1097 }
1098
1099 bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate)
1100 {
1101         for(size_t i = 0; i < fnCandidate->getParamCount(); ++i)
1102         {
1103                 TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
1104                 if(qual == EvqOut || qual == EvqInOut)
1105                 {
1106                         TIntermTyped *node = (aggregate->getSequence())[i]->getAsTyped();
1107                         if(lValueErrorCheck(node->getLine(), "assign", node))
1108                         {
1109                                 error(node->getLine(),
1110                                         "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
1111                                 recover();
1112                                 return true;
1113                         }
1114                 }
1115         }
1116         return false;
1117 }
1118
1119 bool TParseContext::supportsExtension(const char* extension)
1120 {
1121     const TExtensionBehavior& extbehavior = extensionBehavior();
1122     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
1123     return (iter != extbehavior.end());
1124 }
1125
1126 void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
1127 {
1128     pp::SourceLocation loc;
1129     DecodeSourceLoc(line, &loc.file, &loc.line);
1130     directiveHandler.handleExtension(loc, extName, behavior);
1131 }
1132
1133 void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
1134 {
1135     pp::SourceLocation loc;
1136     DecodeSourceLoc(line, &loc.file, &loc.line);
1137     directiveHandler.handlePragma(loc, name, value);
1138 }
1139
1140 /////////////////////////////////////////////////////////////////////////////////
1141 //
1142 // Non-Errors.
1143 //
1144 /////////////////////////////////////////////////////////////////////////////////
1145
1146 const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
1147         const TString *name,
1148         const TSymbol *symbol)
1149 {
1150         const TVariable *variable = NULL;
1151
1152         if(!symbol)
1153         {
1154                 error(location, "undeclared identifier", name->c_str());
1155                 recover();
1156         }
1157         else if(!symbol->isVariable())
1158         {
1159                 error(location, "variable expected", name->c_str());
1160                 recover();
1161         }
1162         else
1163         {
1164                 variable = static_cast<const TVariable*>(symbol);
1165
1166                 if(symbolTable.findBuiltIn(variable->getName(), shaderVersion))
1167                 {
1168                         recover();
1169                 }
1170
1171                 // Reject shaders using both gl_FragData and gl_FragColor
1172                 TQualifier qualifier = variable->getType().getQualifier();
1173                 if(qualifier == EvqFragData)
1174                 {
1175                         mUsesFragData = true;
1176                 }
1177                 else if(qualifier == EvqFragColor)
1178                 {
1179                         mUsesFragColor = true;
1180                 }
1181
1182                 // This validation is not quite correct - it's only an error to write to
1183                 // both FragData and FragColor. For simplicity, and because users shouldn't
1184                 // be rewarded for reading from undefined varaibles, return an error
1185                 // if they are both referenced, rather than assigned.
1186                 if(mUsesFragData && mUsesFragColor)
1187                 {
1188                         error(location, "cannot use both gl_FragData and gl_FragColor", name->c_str());
1189                         recover();
1190                 }
1191         }
1192
1193         if(!variable)
1194         {
1195                 TType type(EbtFloat, EbpUndefined);
1196                 TVariable *fakeVariable = new TVariable(name, type);
1197                 symbolTable.declare(*fakeVariable);
1198                 variable = fakeVariable;
1199         }
1200
1201         return variable;
1202 }
1203
1204 //
1205 // Look up a function name in the symbol table, and make sure it is a function.
1206 //
1207 // Return the function symbol if found, otherwise 0.
1208 //
1209 const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
1210 {
1211     // First find by unmangled name to check whether the function name has been
1212     // hidden by a variable name or struct typename.
1213     const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn);
1214     if (symbol == 0) {
1215         symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
1216     }
1217
1218     if (symbol == 0) {
1219         error(line, "no matching overloaded function found", call->getName().c_str());
1220         return 0;
1221     }
1222
1223     if (!symbol->isFunction()) {
1224         error(line, "function name expected", call->getName().c_str());
1225         return 0;
1226     }
1227
1228     return static_cast<const TFunction*>(symbol);
1229 }
1230
1231 //
1232 // Initializers show up in several places in the grammar.  Have one set of
1233 // code to handle them here.
1234 //
1235 bool TParseContext::executeInitializer(TSourceLoc line, const TString& identifier, const TPublicType& pType,
1236                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
1237 {
1238     TType type = TType(pType);
1239
1240     if (variable == 0) {
1241         if (reservedErrorCheck(line, identifier))
1242             return true;
1243
1244         if (voidErrorCheck(line, identifier, pType.type))
1245             return true;
1246
1247         //
1248         // add variable to symbol table
1249         //
1250         variable = new TVariable(&identifier, type);
1251         if (! symbolTable.declare(*variable)) {
1252             error(line, "redefinition", variable->getName().c_str());
1253             return true;
1254             // don't delete variable, it's used by error recovery, and the pool
1255             // pop will take care of the memory
1256         }
1257     }
1258
1259     //
1260     // identifier must be of type constant, a global, or a temporary
1261     //
1262     TQualifier qualifier = variable->getType().getQualifier();
1263     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) {
1264         error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
1265         return true;
1266     }
1267     //
1268     // test for and propagate constant
1269     //
1270
1271     if (qualifier == EvqConstExpr) {
1272         if (qualifier != initializer->getType().getQualifier()) {
1273             std::stringstream extraInfoStream;
1274             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1275             std::string extraInfo = extraInfoStream.str();
1276             error(line, " assigning non-constant to", "=", extraInfo.c_str());
1277             variable->getType().setQualifier(EvqTemporary);
1278             return true;
1279         }
1280         if (type != initializer->getType()) {
1281             error(line, " non-matching types for const initializer ",
1282                 variable->getType().getQualifierString());
1283             variable->getType().setQualifier(EvqTemporary);
1284             return true;
1285         }
1286         if (initializer->getAsConstantUnion()) {
1287             ConstantUnion* unionArray = variable->getConstPointer();
1288
1289             if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
1290                 *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
1291             } else {
1292                 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
1293             }
1294         } else if (initializer->getAsSymbolNode()) {
1295             const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), shaderVersion);
1296             const TVariable* tVar = static_cast<const TVariable*>(symbol);
1297
1298             ConstantUnion* constArray = tVar->getConstPointer();
1299             variable->shareConstPointer(constArray);
1300         } else {
1301             std::stringstream extraInfoStream;
1302             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1303             std::string extraInfo = extraInfoStream.str();
1304             error(line, " cannot assign to", "=", extraInfo.c_str());
1305             variable->getType().setQualifier(EvqTemporary);
1306             return true;
1307         }
1308     }
1309
1310     if (qualifier != EvqConstExpr) {
1311         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
1312         intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
1313         if (intermNode == 0) {
1314             assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1315             return true;
1316         }
1317     } else
1318         intermNode = 0;
1319
1320     return false;
1321 }
1322
1323 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
1324 {
1325     ASSERT(aggrNode != NULL);
1326     if (!aggrNode->isConstructor())
1327         return false;
1328
1329     bool allConstant = true;
1330
1331     // check if all the child nodes are constants so that they can be inserted into
1332     // the parent node
1333     TIntermSequence &sequence = aggrNode->getSequence() ;
1334     for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
1335         if (!(*p)->getAsTyped()->getAsConstantUnion())
1336             return false;
1337     }
1338
1339     return allConstant;
1340 }
1341
1342 TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
1343 {
1344         TPublicType returnType = typeSpecifier;
1345         returnType.qualifier = qualifier;
1346         returnType.invariant = invariant;
1347         returnType.layoutQualifier = layoutQualifier;
1348
1349         if(typeSpecifier.array)
1350         {
1351                 error(typeSpecifier.line, "not supported", "first-class array");
1352                 recover();
1353                 returnType.clearArrayness();
1354         }
1355
1356         if(shaderVersion < 300)
1357         {
1358                 if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1359                 {
1360                         error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1361                         recover();
1362                 }
1363
1364                 if((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1365                         (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1366                 {
1367                         error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1368                         recover();
1369                 }
1370         }
1371         else
1372         {
1373                 switch(qualifier)
1374                 {
1375                 case EvqSmoothIn:
1376                 case EvqSmoothOut:
1377                 case EvqVertexOut:
1378                 case EvqFragmentIn:
1379                 case EvqCentroidOut:
1380                 case EvqCentroidIn:
1381                         if(typeSpecifier.type == EbtBool)
1382                         {
1383                                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
1384                                 recover();
1385                         }
1386                         if(typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt)
1387                         {
1388                                 error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier));
1389                                 recover();
1390                         }
1391                         break;
1392
1393                 case EvqVertexIn:
1394                 case EvqFragmentOut:
1395                 case EvqFlatIn:
1396                 case EvqFlatOut:
1397                         if(typeSpecifier.type == EbtBool)
1398                         {
1399                                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
1400                                 recover();
1401                         }
1402                         break;
1403
1404                 default: break;
1405                 }
1406         }
1407
1408         return returnType;
1409 }
1410
1411 TIntermAggregate *TParseContext::parseSingleDeclaration(TPublicType &publicType,
1412         const TSourceLoc &identifierOrTypeLocation,
1413         const TString &identifier)
1414 {
1415         TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierOrTypeLocation);
1416
1417         bool emptyDeclaration = (identifier == "");
1418
1419         mDeferredSingleDeclarationErrorCheck = emptyDeclaration;
1420
1421         if(emptyDeclaration)
1422         {
1423                 if(publicType.isUnsizedArray())
1424                 {
1425                         // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an error.
1426                         // It is assumed that this applies to empty declarations as well.
1427                         error(identifierOrTypeLocation, "empty array declaration needs to specify a size", identifier.c_str());
1428                 }
1429         }
1430         else
1431         {
1432                 if(singleDeclarationErrorCheck(publicType, identifierOrTypeLocation))
1433                         recover();
1434
1435                 if(nonInitErrorCheck(identifierOrTypeLocation, identifier, publicType))
1436                         recover();
1437
1438                 TVariable *variable = nullptr;
1439                 if(!declareVariable(identifierOrTypeLocation, identifier, TType(publicType), &variable))
1440                         recover();
1441
1442                 if(variable && symbol)
1443                         symbol->setId(variable->getUniqueId());
1444         }
1445
1446         return intermediate.makeAggregate(symbol, identifierOrTypeLocation);
1447 }
1448
1449 TIntermAggregate *TParseContext::parseSingleArrayDeclaration(TPublicType &publicType,
1450         const TSourceLoc &identifierLocation,
1451         const TString &identifier,
1452         const TSourceLoc &indexLocation,
1453         TIntermTyped *indexExpression)
1454 {
1455         mDeferredSingleDeclarationErrorCheck = false;
1456
1457         if(singleDeclarationErrorCheck(publicType, identifierLocation))
1458                 recover();
1459
1460         if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1461                 recover();
1462
1463         if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1464         {
1465                 recover();
1466         }
1467
1468         TType arrayType(publicType);
1469
1470         int size;
1471         if(arraySizeErrorCheck(identifierLocation, indexExpression, size))
1472         {
1473                 recover();
1474         }
1475         // Make the type an array even if size check failed.
1476         // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1477         arrayType.setArraySize(size);
1478
1479         TVariable *variable = nullptr;
1480         if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
1481                 recover();
1482
1483         TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
1484         if(variable && symbol)
1485                 symbol->setId(variable->getUniqueId());
1486
1487         return intermediate.makeAggregate(symbol, identifierLocation);
1488 }
1489
1490 TIntermAggregate *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
1491         const TSourceLoc &identifierLocation,
1492         const TString &identifier,
1493         const TSourceLoc &initLocation,
1494         TIntermTyped *initializer)
1495 {
1496         mDeferredSingleDeclarationErrorCheck = false;
1497
1498         if(singleDeclarationErrorCheck(publicType, identifierLocation))
1499                 recover();
1500
1501         TIntermNode *intermNode = nullptr;
1502         if(!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
1503         {
1504                 //
1505                 // Build intermediate representation
1506                 //
1507                 return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : nullptr;
1508         }
1509         else
1510         {
1511                 recover();
1512                 return nullptr;
1513         }
1514 }
1515
1516 TIntermAggregate *TParseContext::parseSingleArrayInitDeclaration(TPublicType &publicType,
1517         const TSourceLoc &identifierLocation,
1518         const TString &identifier,
1519         const TSourceLoc &indexLocation,
1520         TIntermTyped *indexExpression,
1521         const TSourceLoc &initLocation,
1522         TIntermTyped *initializer)
1523 {
1524         mDeferredSingleDeclarationErrorCheck = false;
1525
1526         if(singleDeclarationErrorCheck(publicType, identifierLocation))
1527                 recover();
1528
1529         if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1530         {
1531                 recover();
1532         }
1533
1534         TPublicType arrayType(publicType);
1535
1536         int size = 0;
1537         // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
1538         if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
1539         {
1540                 recover();
1541         }
1542         // Make the type an array even if size check failed.
1543         // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1544         arrayType.setArray(true, size);
1545
1546         // initNode will correspond to the whole of "type b[n] = initializer".
1547         TIntermNode *initNode = nullptr;
1548         if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, initNode))
1549         {
1550                 return initNode ? intermediate.makeAggregate(initNode, initLocation) : nullptr;
1551         }
1552         else
1553         {
1554                 recover();
1555                 return nullptr;
1556         }
1557 }
1558
1559 TIntermAggregate *TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc,
1560         const TSourceLoc &identifierLoc,
1561         const TString *identifier,
1562         const TSymbol *symbol)
1563 {
1564         // invariant declaration
1565         if(globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying"))
1566         {
1567                 recover();
1568         }
1569
1570         if(!symbol)
1571         {
1572                 error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str());
1573                 recover();
1574                 return nullptr;
1575         }
1576         else
1577         {
1578                 const TString kGlFrontFacing("gl_FrontFacing");
1579                 if(*identifier == kGlFrontFacing)
1580                 {
1581                         error(identifierLoc, "identifier should not be declared as invariant", identifier->c_str());
1582                         recover();
1583                         return nullptr;
1584                 }
1585                 symbolTable.addInvariantVarying(std::string(identifier->c_str()));
1586                 const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
1587                 ASSERT(variable);
1588                 const TType &type = variable->getType();
1589                 TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(),
1590                         *identifier, type, identifierLoc);
1591
1592                 TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc);
1593                 aggregate->setOp(EOpInvariantDeclaration);
1594                 return aggregate;
1595         }
1596 }
1597
1598 TIntermAggregate *TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1599         const TSourceLoc &identifierLocation, const TString &identifier)
1600 {
1601         // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1602         if(mDeferredSingleDeclarationErrorCheck)
1603         {
1604                 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1605                         recover();
1606                 mDeferredSingleDeclarationErrorCheck = false;
1607         }
1608
1609         if(locationDeclaratorListCheck(identifierLocation, publicType))
1610                 recover();
1611
1612         if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1613                 recover();
1614
1615         TVariable *variable = nullptr;
1616         if(!declareVariable(identifierLocation, identifier, TType(publicType), &variable))
1617                 recover();
1618
1619         TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
1620         if(variable && symbol)
1621                 symbol->setId(variable->getUniqueId());
1622
1623         return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
1624 }
1625
1626 TIntermAggregate *TParseContext::parseArrayDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1627         const TSourceLoc &identifierLocation, const TString &identifier,
1628         const TSourceLoc &arrayLocation, TIntermTyped *indexExpression)
1629 {
1630         // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1631         if(mDeferredSingleDeclarationErrorCheck)
1632         {
1633                 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1634                         recover();
1635                 mDeferredSingleDeclarationErrorCheck = false;
1636         }
1637
1638         if(locationDeclaratorListCheck(identifierLocation, publicType))
1639                 recover();
1640
1641         if(nonInitErrorCheck(identifierLocation, identifier, publicType))
1642                 recover();
1643
1644         if(arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType))
1645         {
1646                 recover();
1647         }
1648         else
1649         {
1650                 TType arrayType = TType(publicType);
1651                 int size;
1652                 if(arraySizeErrorCheck(arrayLocation, indexExpression, size))
1653                 {
1654                         recover();
1655                 }
1656                 arrayType.setArraySize(size);
1657
1658                 TVariable *variable = nullptr;
1659                 if(!declareVariable(identifierLocation, identifier, arrayType, &variable))
1660                         recover();
1661
1662                 TIntermSymbol *symbol = intermediate.addSymbol(0, identifier, arrayType, identifierLocation);
1663                 if(variable && symbol)
1664                         symbol->setId(variable->getUniqueId());
1665
1666                 return intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation);
1667         }
1668
1669         return nullptr;
1670 }
1671
1672 TIntermAggregate *TParseContext::parseInitDeclarator(const TPublicType &publicType, TIntermAggregate *aggregateDeclaration,
1673         const TSourceLoc &identifierLocation, const TString &identifier,
1674         const TSourceLoc &initLocation, TIntermTyped *initializer)
1675 {
1676         // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1677         if(mDeferredSingleDeclarationErrorCheck)
1678         {
1679                 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1680                         recover();
1681                 mDeferredSingleDeclarationErrorCheck = false;
1682         }
1683
1684         if(locationDeclaratorListCheck(identifierLocation, publicType))
1685                 recover();
1686
1687         TIntermNode *intermNode = nullptr;
1688         if(!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
1689         {
1690                 //
1691                 // build the intermediate representation
1692                 //
1693                 if(intermNode)
1694                 {
1695                         return intermediate.growAggregate(aggregateDeclaration, intermNode, initLocation);
1696                 }
1697                 else
1698                 {
1699                         return aggregateDeclaration;
1700                 }
1701         }
1702         else
1703         {
1704                 recover();
1705                 return nullptr;
1706         }
1707 }
1708
1709 TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &publicType,
1710         TIntermAggregate *aggregateDeclaration,
1711         const TSourceLoc &identifierLocation,
1712         const TString &identifier,
1713         const TSourceLoc &indexLocation,
1714         TIntermTyped *indexExpression,
1715         const TSourceLoc &initLocation, TIntermTyped *initializer)
1716 {
1717         // If the declaration starting this declarator list was empty (example: int,), some checks were not performed.
1718         if(mDeferredSingleDeclarationErrorCheck)
1719         {
1720                 if(singleDeclarationErrorCheck(publicType, identifierLocation))
1721                         recover();
1722                 mDeferredSingleDeclarationErrorCheck = false;
1723         }
1724
1725         if(locationDeclaratorListCheck(identifierLocation, publicType))
1726                 recover();
1727
1728         if(arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
1729         {
1730                 recover();
1731         }
1732
1733         TPublicType arrayType(publicType);
1734
1735         int size = 0;
1736         // If indexExpression is nullptr, then the array will eventually get its size implicitly from the initializer.
1737         if(indexExpression != nullptr && arraySizeErrorCheck(identifierLocation, indexExpression, size))
1738         {
1739                 recover();
1740         }
1741         // Make the type an array even if size check failed.
1742         // This ensures useless error messages regarding the variable's non-arrayness won't follow.
1743         arrayType.setArray(true, size);
1744
1745         // initNode will correspond to the whole of "b[n] = initializer".
1746         TIntermNode *initNode = nullptr;
1747         if(!executeInitializer(identifierLocation, identifier, arrayType, initializer, initNode))
1748         {
1749                 if(initNode)
1750                 {
1751                         return intermediate.growAggregate(aggregateDeclaration, initNode, initLocation);
1752                 }
1753                 else
1754                 {
1755                         return aggregateDeclaration;
1756                 }
1757         }
1758         else
1759         {
1760                 recover();
1761                 return nullptr;
1762         }
1763 }
1764
1765 // This function is used to test for the correctness of the parameters passed to various constructor functions
1766 // and also convert them to the right datatype if it is allowed and required.
1767 //
1768 // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
1769 //
1770 TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
1771 {
1772     TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
1773
1774     if(!aggregateArguments)
1775     {
1776         aggregateArguments = new TIntermAggregate;
1777         aggregateArguments->getSequence().push_back(arguments);
1778     }
1779
1780     if(op == EOpConstructStruct)
1781     {
1782         const TFieldList &fields = type->getStruct()->fields();
1783         TIntermSequence &args = aggregateArguments->getSequence();
1784
1785         for(size_t i = 0; i < fields.size(); i++)
1786         {
1787             if(args[i]->getAsTyped()->getType() != *fields[i]->type())
1788             {
1789                 error(line, "Structure constructor arguments do not match structure fields", "Error");
1790                 recover();
1791
1792                 return 0;
1793             }
1794         }
1795     }
1796
1797     // Turn the argument list itself into a constructor
1798     TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
1799     TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
1800     if(constConstructor)
1801     {
1802         return constConstructor;
1803     }
1804
1805     return constructor;
1806 }
1807
1808 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
1809 {
1810     bool canBeFolded = areAllChildConst(aggrNode);
1811     aggrNode->setType(type);
1812     if (canBeFolded) {
1813         bool returnVal = false;
1814         ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
1815         if (aggrNode->getSequence().size() == 1)  {
1816             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
1817         }
1818         else {
1819             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
1820         }
1821         if (returnVal)
1822             return 0;
1823
1824         return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
1825     }
1826
1827     return 0;
1828 }
1829
1830 //
1831 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
1832 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
1833 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
1834 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
1835 // a constant matrix.
1836 //
1837 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
1838 {
1839     TIntermTyped* typedNode;
1840     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1841
1842     ConstantUnion *unionArray;
1843     if (tempConstantNode) {
1844         unionArray = tempConstantNode->getUnionArrayPointer();
1845
1846         if (!unionArray) {
1847             return node;
1848         }
1849     } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
1850         error(line, "Cannot offset into the vector", "Error");
1851         recover();
1852
1853         return 0;
1854     }
1855
1856     ConstantUnion* constArray = new ConstantUnion[fields.num];
1857
1858     for (int i = 0; i < fields.num; i++) {
1859         if (fields.offsets[i] >= node->getType().getObjectSize()) {
1860             std::stringstream extraInfoStream;
1861             extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
1862             std::string extraInfo = extraInfoStream.str();
1863             error(line, "", "[", extraInfo.c_str());
1864             recover();
1865             fields.offsets[i] = 0;
1866         }
1867
1868         constArray[i] = unionArray[fields.offsets[i]];
1869
1870     }
1871     typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
1872     return typedNode;
1873 }
1874
1875 //
1876 // This function returns the column being accessed from a constant matrix. The values are retrieved from
1877 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
1878 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
1879 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
1880 //
1881 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
1882 {
1883     TIntermTyped* typedNode;
1884     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1885
1886     if (index >= node->getType().getNominalSize()) {
1887         std::stringstream extraInfoStream;
1888         extraInfoStream << "matrix field selection out of range '" << index << "'";
1889         std::string extraInfo = extraInfoStream.str();
1890         error(line, "", "[", extraInfo.c_str());
1891         recover();
1892         index = 0;
1893     }
1894
1895     if (tempConstantNode) {
1896          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1897          int size = tempConstantNode->getType().getNominalSize();
1898          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
1899     } else {
1900         error(line, "Cannot offset into the matrix", "Error");
1901         recover();
1902
1903         return 0;
1904     }
1905
1906     return typedNode;
1907 }
1908
1909
1910 //
1911 // This function returns an element of an array accessed from a constant array. The values are retrieved from
1912 // the symbol table and parse-tree is built for the type of the element. The input
1913 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
1914 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
1915 //
1916 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
1917 {
1918     TIntermTyped* typedNode;
1919     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1920     TType arrayElementType = node->getType();
1921     arrayElementType.clearArrayness();
1922
1923     if (index >= node->getType().getArraySize()) {
1924         std::stringstream extraInfoStream;
1925         extraInfoStream << "array field selection out of range '" << index << "'";
1926         std::string extraInfo = extraInfoStream.str();
1927         error(line, "", "[", extraInfo.c_str());
1928         recover();
1929         index = 0;
1930     }
1931
1932     int arrayElementSize = arrayElementType.getObjectSize();
1933
1934     if (tempConstantNode) {
1935          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1936          typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
1937     } else {
1938         error(line, "Cannot offset into the array", "Error");
1939         recover();
1940
1941         return 0;
1942     }
1943
1944     return typedNode;
1945 }
1946
1947
1948 //
1949 // This function returns the value of a particular field inside a constant structure from the symbol table.
1950 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
1951 // function and returns the parse-tree with the values of the embedded/nested struct.
1952 //
1953 TIntermTyped* TParseContext::addConstStruct(const TString& identifier, TIntermTyped* node, TSourceLoc line)
1954 {
1955     const TFieldList &fields = node->getType().getStruct()->fields();
1956     TIntermTyped *typedNode;
1957     int instanceSize = 0;
1958     unsigned int index = 0;
1959     TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
1960
1961     for ( index = 0; index < fields.size(); ++index) {
1962         if (fields[index]->name() == identifier) {
1963             break;
1964         } else {
1965             instanceSize += fields[index]->type()->getObjectSize();
1966         }
1967     }
1968
1969     if (tempConstantNode) {
1970          ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
1971
1972          typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
1973     } else {
1974         error(line, "Cannot offset into the structure", "Error");
1975         recover();
1976
1977         return 0;
1978     }
1979
1980     return typedNode;
1981 }
1982
1983 //
1984 // Parse an array index expression
1985 //
1986 TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression)
1987 {
1988         TIntermTyped *indexedExpression = NULL;
1989
1990         if(!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
1991         {
1992                 if(baseExpression->getAsSymbolNode())
1993                 {
1994                         error(location, " left of '[' is not of type array, matrix, or vector ",
1995                                 baseExpression->getAsSymbolNode()->getSymbol().c_str());
1996                 }
1997                 else
1998                 {
1999                         error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
2000                 }
2001                 recover();
2002         }
2003
2004         TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
2005
2006         if(indexExpression->getQualifier() == EvqConstExpr && indexConstantUnion)
2007         {
2008                 int index = indexConstantUnion->getIConst(0);
2009                 if(index < 0)
2010                 {
2011                         std::stringstream infoStream;
2012                         infoStream << index;
2013                         std::string info = infoStream.str();
2014                         error(location, "negative index", info.c_str());
2015                         recover();
2016                         index = 0;
2017                 }
2018                 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2019                 {
2020                         if(baseExpression->isArray())
2021                         {
2022                                 // constant folding for arrays
2023                                 indexedExpression = addConstArrayNode(index, baseExpression, location);
2024                         }
2025                         else if(baseExpression->isVector())
2026                         {
2027                                 // constant folding for vectors
2028                                 TVectorFields fields;
2029                                 fields.num = 1;
2030                                 fields.offsets[0] = index; // need to do it this way because v.xy sends fields integer array
2031                                 indexedExpression = addConstVectorNode(fields, baseExpression, location);
2032                         }
2033                         else if(baseExpression->isMatrix())
2034                         {
2035                                 // constant folding for matrices
2036                                 indexedExpression = addConstMatrixNode(index, baseExpression, location);
2037                         }
2038                 }
2039                 else
2040                 {
2041                         int safeIndex = -1;
2042
2043                         if(baseExpression->isArray())
2044                         {
2045                                 if(index >= baseExpression->getType().getArraySize())
2046                                 {
2047                                         std::stringstream extraInfoStream;
2048                                         extraInfoStream << "array index out of range '" << index << "'";
2049                                         std::string extraInfo = extraInfoStream.str();
2050                                         error(location, "", "[", extraInfo.c_str());
2051                                         recover();
2052                                         safeIndex = baseExpression->getType().getArraySize() - 1;
2053                                 }
2054                         }
2055                         else if((baseExpression->isVector() || baseExpression->isMatrix()) &&
2056                                 baseExpression->getType().getNominalSize() <= index)
2057                         {
2058                                 std::stringstream extraInfoStream;
2059                                 extraInfoStream << "field selection out of range '" << index << "'";
2060                                 std::string extraInfo = extraInfoStream.str();
2061                                 error(location, "", "[", extraInfo.c_str());
2062                                 recover();
2063                                 safeIndex = baseExpression->getType().getNominalSize() - 1;
2064                         }
2065
2066                         // Don't modify the data of the previous constant union, because it can point
2067                         // to builtins, like gl_MaxDrawBuffers. Instead use a new sanitized object.
2068                         if(safeIndex != -1)
2069                         {
2070                                 ConstantUnion *safeConstantUnion = new ConstantUnion();
2071                                 safeConstantUnion->setIConst(safeIndex);
2072                                 indexConstantUnion->replaceConstantUnion(safeConstantUnion);
2073                         }
2074
2075                         indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
2076                 }
2077         }
2078         else
2079         {
2080                 if(baseExpression->isInterfaceBlock())
2081                 {
2082                         error(location, "",
2083                                 "[", "array indexes for interface blocks arrays must be constant integral expressions");
2084                         recover();
2085                 }
2086                 // FIXME
2087                 /*
2088                 else if(baseExpression->getQualifier() == EvqFragmentOut)
2089                 {
2090                         error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions");
2091                         recover();
2092                 }
2093                 */
2094
2095                 indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location);
2096         }
2097
2098         if(indexedExpression == 0)
2099         {
2100                 ConstantUnion *unionArray = new ConstantUnion[1];
2101                 unionArray->setFConst(0.0f);
2102                 indexedExpression = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConstExpr), location);
2103         }
2104         else if(baseExpression->isArray())
2105         {
2106                 const TType &baseType = baseExpression->getType();
2107                 if(baseType.getStruct())
2108                 {
2109                         TType copyOfType(baseType.getStruct());
2110                         indexedExpression->setType(copyOfType);
2111                 }
2112                 else if(baseType.isInterfaceBlock())
2113                 {
2114                         TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0);
2115                         indexedExpression->setType(copyOfType);
2116                 }
2117                 else
2118                 {
2119                         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2120                                 EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
2121                                 static_cast<unsigned char>(baseExpression->getSecondarySize())));
2122                 }
2123
2124                 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2125                 {
2126                         indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
2127                 }
2128         }
2129         else if(baseExpression->isMatrix())
2130         {
2131                 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
2132                 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2133                         qualifier, static_cast<unsigned char>(baseExpression->getSecondarySize())));
2134         }
2135         else if(baseExpression->isVector())
2136         {
2137                 TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConstExpr ? EvqConstExpr : EvqTemporary;
2138                 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier));
2139         }
2140         else
2141         {
2142                 indexedExpression->setType(baseExpression->getType());
2143         }
2144
2145         return indexedExpression;
2146 }
2147
2148 TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc &dotLocation,
2149         const TString &fieldString, const TSourceLoc &fieldLocation)
2150 {
2151         TIntermTyped *indexedExpression = NULL;
2152
2153         if(baseExpression->isArray())
2154         {
2155                 error(fieldLocation, "cannot apply dot operator to an array", ".");
2156                 recover();
2157         }
2158
2159         if(baseExpression->isVector())
2160         {
2161                 TVectorFields fields;
2162                 if(!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation))
2163                 {
2164                         fields.num = 1;
2165                         fields.offsets[0] = 0;
2166                         recover();
2167                 }
2168
2169                 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2170                 {
2171                         // constant folding for vector fields
2172                         indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation);
2173                         if(indexedExpression == 0)
2174                         {
2175                                 recover();
2176                                 indexedExpression = baseExpression;
2177                         }
2178                         else
2179                         {
2180                                 indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2181                                         EvqConstExpr, (unsigned char)(fieldString).size()));
2182                         }
2183                 }
2184                 else
2185                 {
2186                         TString vectorString = fieldString;
2187                         TIntermTyped *index = intermediate.addSwizzle(fields, fieldLocation);
2188                         indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation);
2189                         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2190                                 EvqTemporary, (unsigned char)vectorString.size()));
2191                 }
2192         }
2193         else if(baseExpression->isMatrix())
2194         {
2195                 TMatrixFields fields;
2196                 if(!parseMatrixFields(fieldString, baseExpression->getNominalSize(), baseExpression->getSecondarySize(), fields, fieldLocation))
2197                 {
2198                         fields.wholeRow = false;
2199                         fields.wholeCol = false;
2200                         fields.row = 0;
2201                         fields.col = 0;
2202                         recover();
2203                 }
2204
2205                 if(fields.wholeRow || fields.wholeCol)
2206                 {
2207                         error(dotLocation, " non-scalar fields not implemented yet", ".");
2208                         recover();
2209                         ConstantUnion *unionArray = new ConstantUnion[1];
2210                         unionArray->setIConst(0);
2211                         TIntermTyped *index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr),
2212                                 fieldLocation);
2213                         indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
2214                         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),
2215                                 EvqTemporary, static_cast<unsigned char>(baseExpression->getNominalSize()),
2216                                 static_cast<unsigned char>(baseExpression->getSecondarySize())));
2217                 }
2218                 else
2219                 {
2220                         ConstantUnion *unionArray = new ConstantUnion[1];
2221                         unionArray->setIConst(fields.col * baseExpression->getSecondarySize() + fields.row);
2222                         TIntermTyped *index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr),
2223                                 fieldLocation);
2224                         indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation);
2225                         indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision()));
2226                 }
2227         }
2228         else if(baseExpression->getBasicType() == EbtStruct)
2229         {
2230                 bool fieldFound = false;
2231                 const TFieldList &fields = baseExpression->getType().getStruct()->fields();
2232                 if(fields.empty())
2233                 {
2234                         error(dotLocation, "structure has no fields", "Internal Error");
2235                         recover();
2236                         indexedExpression = baseExpression;
2237                 }
2238                 else
2239                 {
2240                         unsigned int i;
2241                         for(i = 0; i < fields.size(); ++i)
2242                         {
2243                                 if(fields[i]->name() == fieldString)
2244                                 {
2245                                         fieldFound = true;
2246                                         break;
2247                                 }
2248                         }
2249                         if(fieldFound)
2250                         {
2251                                 if(baseExpression->getType().getQualifier() == EvqConstExpr)
2252                                 {
2253                                         indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation);
2254                                         if(indexedExpression == 0)
2255                                         {
2256                                                 recover();
2257                                                 indexedExpression = baseExpression;
2258                                         }
2259                                         else
2260                                         {
2261                                                 indexedExpression->setType(*fields[i]->type());
2262                                                 // change the qualifier of the return type, not of the structure field
2263                                                 // as the structure definition is shared between various structures.
2264                                                 indexedExpression->getTypePointer()->setQualifier(EvqConstExpr);
2265                                         }
2266                                 }
2267                                 else
2268                                 {
2269                                         ConstantUnion *unionArray = new ConstantUnion[1];
2270                                         unionArray->setIConst(i);
2271                                         TIntermTyped *index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2272                                         indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation);
2273                                         indexedExpression->setType(*fields[i]->type());
2274                                 }
2275                         }
2276                         else
2277                         {
2278                                 error(dotLocation, " no such field in structure", fieldString.c_str());
2279                                 recover();
2280                                 indexedExpression = baseExpression;
2281                         }
2282                 }
2283         }
2284         else if(baseExpression->isInterfaceBlock())
2285         {
2286                 bool fieldFound = false;
2287                 const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
2288                 if(fields.empty())
2289                 {
2290                         error(dotLocation, "interface block has no fields", "Internal Error");
2291                         recover();
2292                         indexedExpression = baseExpression;
2293                 }
2294                 else
2295                 {
2296                         unsigned int i;
2297                         for(i = 0; i < fields.size(); ++i)
2298                         {
2299                                 if(fields[i]->name() == fieldString)
2300                                 {
2301                                         fieldFound = true;
2302                                         break;
2303                                 }
2304                         }
2305                         if(fieldFound)
2306                         {
2307                                 ConstantUnion *unionArray = new ConstantUnion[1];
2308                                 unionArray->setIConst(i);
2309                                 TIntermTyped *index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation);
2310                                 indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index,
2311                                         dotLocation);
2312                                 indexedExpression->setType(*fields[i]->type());
2313                         }
2314                         else
2315                         {
2316                                 error(dotLocation, " no such field in interface block", fieldString.c_str());
2317                                 recover();
2318                                 indexedExpression = baseExpression;
2319                         }
2320                 }
2321         }
2322         else
2323         {
2324                 if(shaderVersion < 300)
2325                 {
2326                         error(dotLocation, " field selection requires structure, vector, or matrix on left hand side",
2327                                 fieldString.c_str());
2328                 }
2329                 else
2330                 {
2331                         error(dotLocation,
2332                                 " field selection requires structure, vector, matrix, or interface block on left hand side",
2333                                 fieldString.c_str());
2334                 }
2335                 recover();
2336                 indexedExpression = baseExpression;
2337         }
2338
2339         return indexedExpression;
2340 }
2341
2342 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
2343 {
2344     TLayoutQualifier qualifier;
2345
2346     qualifier.location = -1;
2347         qualifier.matrixPacking = EmpUnspecified;
2348         qualifier.blockStorage = EbsUnspecified;
2349
2350         if(qualifierType == "shared")
2351         {
2352                 qualifier.blockStorage = EbsShared;
2353         }
2354         else if(qualifierType == "packed")
2355         {
2356                 qualifier.blockStorage = EbsPacked;
2357         }
2358         else if(qualifierType == "std140")
2359         {
2360                 qualifier.blockStorage = EbsStd140;
2361         }
2362         else if(qualifierType == "row_major")
2363         {
2364                 qualifier.matrixPacking = EmpRowMajor;
2365         }
2366         else if(qualifierType == "column_major")
2367         {
2368                 qualifier.matrixPacking = EmpColumnMajor;
2369         }
2370         else if(qualifierType == "location")
2371     {
2372         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
2373         recover();
2374     }
2375     else
2376     {
2377         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
2378         recover();
2379     }
2380
2381     return qualifier;
2382 }
2383
2384 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
2385 {
2386     TLayoutQualifier qualifier;
2387
2388     qualifier.location = -1;
2389     qualifier.matrixPacking = EmpUnspecified;
2390     qualifier.blockStorage = EbsUnspecified;
2391
2392     if (qualifierType != "location")
2393     {
2394         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
2395         recover();
2396     }
2397     else
2398     {
2399         // must check that location is non-negative
2400         if (intValue < 0)
2401         {
2402             error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
2403             recover();
2404         }
2405         else
2406         {
2407             qualifier.location = intValue;
2408         }
2409     }
2410
2411     return qualifier;
2412 }
2413
2414 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
2415 {
2416     TLayoutQualifier joinedQualifier = leftQualifier;
2417
2418     if (rightQualifier.location != -1)
2419     {
2420         joinedQualifier.location = rightQualifier.location;
2421     }
2422         if(rightQualifier.matrixPacking != EmpUnspecified)
2423         {
2424                 joinedQualifier.matrixPacking = rightQualifier.matrixPacking;
2425         }
2426         if(rightQualifier.blockStorage != EbsUnspecified)
2427         {
2428                 joinedQualifier.blockStorage = rightQualifier.blockStorage;
2429         }
2430
2431     return joinedQualifier;
2432 }
2433
2434
2435 TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
2436         const TSourceLoc &storageLoc, TQualifier storageQualifier)
2437 {
2438         TQualifier mergedQualifier = EvqSmoothIn;
2439
2440         if(storageQualifier == EvqFragmentIn) {
2441                 if(interpolationQualifier == EvqSmooth)
2442                         mergedQualifier = EvqSmoothIn;
2443                 else if(interpolationQualifier == EvqFlat)
2444                         mergedQualifier = EvqFlatIn;
2445                 else UNREACHABLE();
2446         }
2447         else if(storageQualifier == EvqCentroidIn) {
2448                 if(interpolationQualifier == EvqSmooth)
2449                         mergedQualifier = EvqCentroidIn;
2450                 else if(interpolationQualifier == EvqFlat)
2451                         mergedQualifier = EvqFlatIn;
2452                 else UNREACHABLE();
2453         }
2454         else if(storageQualifier == EvqVertexOut) {
2455                 if(interpolationQualifier == EvqSmooth)
2456                         mergedQualifier = EvqSmoothOut;
2457                 else if(interpolationQualifier == EvqFlat)
2458                         mergedQualifier = EvqFlatOut;
2459                 else UNREACHABLE();
2460         }
2461         else if(storageQualifier == EvqCentroidOut) {
2462                 if(interpolationQualifier == EvqSmooth)
2463                         mergedQualifier = EvqCentroidOut;
2464                 else if(interpolationQualifier == EvqFlat)
2465                         mergedQualifier = EvqFlatOut;
2466                 else UNREACHABLE();
2467         }
2468         else {
2469                 error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString(interpolationQualifier));
2470                 recover();
2471
2472                 mergedQualifier = storageQualifier;
2473         }
2474
2475         TPublicType type;
2476         type.setBasic(EbtVoid, mergedQualifier, storageLoc);
2477         return type;
2478 }
2479
2480 TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList)
2481 {
2482         if(voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier.type))
2483         {
2484                 recover();
2485         }
2486
2487         for(unsigned int i = 0; i < fieldList->size(); ++i)
2488         {
2489                 //
2490                 // Careful not to replace already known aspects of type, like array-ness
2491                 //
2492                 TType *type = (*fieldList)[i]->type();
2493                 type->setBasicType(typeSpecifier.type);
2494                 type->setNominalSize(typeSpecifier.primarySize);
2495                 type->setSecondarySize(typeSpecifier.secondarySize);
2496                 type->setPrecision(typeSpecifier.precision);
2497                 type->setQualifier(typeSpecifier.qualifier);
2498                 type->setLayoutQualifier(typeSpecifier.layoutQualifier);
2499
2500                 // don't allow arrays of arrays
2501                 if(type->isArray())
2502                 {
2503                         if(arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier))
2504                                 recover();
2505                 }
2506                 if(typeSpecifier.array)
2507                         type->setArraySize(typeSpecifier.arraySize);
2508                 if(typeSpecifier.userDef)
2509                 {
2510                         type->setStruct(typeSpecifier.userDef->getStruct());
2511                 }
2512
2513                 if(structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i]))
2514                 {
2515                         recover();
2516                 }
2517         }
2518
2519         return fieldList;
2520 }
2521
2522 TPublicType TParseContext::addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine,
2523         const TString *structName, TFieldList *fieldList)
2524 {
2525         TStructure *structure = new TStructure(structName, fieldList);
2526         TType *structureType = new TType(structure);
2527
2528         // Store a bool in the struct if we're at global scope, to allow us to
2529         // skip the local struct scoping workaround in HLSL.
2530         structure->setUniqueId(TSymbolTableLevel::nextUniqueId());
2531         structure->setAtGlobalScope(symbolTable.atGlobalLevel());
2532
2533         if(!structName->empty())
2534         {
2535                 if(reservedErrorCheck(nameLine, *structName))
2536                 {
2537                         recover();
2538                 }
2539                 TVariable *userTypeDef = new TVariable(structName, *structureType, true);
2540                 if(!symbolTable.declare(*userTypeDef))
2541                 {
2542                         error(nameLine, "redefinition", structName->c_str(), "struct");
2543                         recover();
2544                 }
2545         }
2546
2547         // ensure we do not specify any storage qualifiers on the struct members
2548         for(unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
2549         {
2550                 const TField &field = *(*fieldList)[typeListIndex];
2551                 const TQualifier qualifier = field.type()->getQualifier();
2552                 switch(qualifier)
2553                 {
2554                 case EvqGlobal:
2555                 case EvqTemporary:
2556                         break;
2557                 default:
2558                         error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier));
2559                         recover();
2560                         break;
2561                 }
2562         }
2563
2564         TPublicType publicType;
2565         publicType.setBasic(EbtStruct, EvqTemporary, structLine);
2566         publicType.userDef = structureType;
2567         exitStructDeclaration();
2568
2569         return publicType;
2570 }
2571
2572 bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
2573 {
2574     ++structNestingLevel;
2575
2576     // Embedded structure definitions are not supported per GLSL ES spec.
2577     // They aren't allowed in GLSL either, but we need to detect this here
2578     // so we don't rely on the GLSL compiler to catch it.
2579     if (structNestingLevel > 1) {
2580         error(line, "", "Embedded struct definitions are not allowed");
2581         return true;
2582     }
2583
2584     return false;
2585 }
2586
2587 void TParseContext::exitStructDeclaration()
2588 {
2589     --structNestingLevel;
2590 }
2591
2592 bool TParseContext::structNestingErrorCheck(const TSourceLoc &line, const TField &field)
2593 {
2594         static const int kWebGLMaxStructNesting = 4;
2595
2596         if(field.type()->getBasicType() != EbtStruct)
2597         {
2598                 return false;
2599         }
2600
2601         // We're already inside a structure definition at this point, so add
2602         // one to the field's struct nesting.
2603         if(1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
2604         {
2605                 std::stringstream reasonStream;
2606                 reasonStream << "Reference of struct type "
2607                         << field.type()->getStruct()->name().c_str()
2608                         << " exceeds maximum allowed nesting level of "
2609                         << kWebGLMaxStructNesting;
2610                 std::string reason = reasonStream.str();
2611                 error(line, reason.c_str(), field.name().c_str(), "");
2612                 return true;
2613         }
2614
2615         return false;
2616 }
2617
2618 TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc, const TType *funcReturnType)
2619 {
2620         if(child == nullptr)
2621         {
2622                 return nullptr;
2623         }
2624
2625         switch(op)
2626         {
2627         case EOpLogicalNot:
2628                 if(child->getBasicType() != EbtBool ||
2629                         child->isMatrix() ||
2630                         child->isArray() ||
2631                         child->isVector())
2632                 {
2633                         return nullptr;
2634                 }
2635                 break;
2636         case EOpBitwiseNot:
2637                 if((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
2638                         child->isMatrix() ||
2639                         child->isArray())
2640                 {
2641                         return nullptr;
2642                 }
2643                 break;
2644         case EOpPostIncrement:
2645         case EOpPreIncrement:
2646         case EOpPostDecrement:
2647         case EOpPreDecrement:
2648         case EOpNegative:
2649                 if(child->getBasicType() == EbtStruct ||
2650                         child->getBasicType() == EbtBool ||
2651                         child->isArray())
2652                 {
2653                         return nullptr;
2654                 }
2655                 // Operators for built-ins are already type checked against their prototype.
2656         default:
2657                 break;
2658         }
2659
2660         return intermediate.addUnaryMath(op, child, loc); // FIXME , funcReturnType);
2661 }
2662
2663 TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
2664 {
2665         TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
2666         if(node == nullptr)
2667         {
2668                 unaryOpError(loc, getOperatorString(op), child->getCompleteString());
2669                 recover();
2670                 return child;
2671         }
2672         return node;
2673 }
2674
2675 TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
2676 {
2677         if(lValueErrorCheck(loc, getOperatorString(op), child))
2678                 recover();
2679         return addUnaryMath(op, child, loc);
2680 }
2681
2682 bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc)
2683 {
2684         if(left->isArray() || right->isArray())
2685         {
2686                 if(shaderVersion < 300)
2687                 {
2688                         error(loc, "Invalid operation for arrays", getOperatorString(op));
2689                         return false;
2690                 }
2691
2692                 if(left->isArray() != right->isArray())
2693                 {
2694                         error(loc, "array / non-array mismatch", getOperatorString(op));
2695                         return false;
2696                 }
2697
2698                 switch(op)
2699                 {
2700                 case EOpEqual:
2701                 case EOpNotEqual:
2702                 case EOpAssign:
2703                 case EOpInitialize:
2704                         break;
2705                 default:
2706                         error(loc, "Invalid operation for arrays", getOperatorString(op));
2707                         return false;
2708                 }
2709                 // At this point, size of implicitly sized arrays should be resolved.
2710                 if(left->getArraySize() != right->getArraySize())
2711                 {
2712                         error(loc, "array size mismatch", getOperatorString(op));
2713                         return false;
2714                 }
2715         }
2716
2717         // Check ops which require integer / ivec parameters
2718         bool isBitShift = false;
2719         switch(op)
2720         {
2721         case EOpBitShiftLeft:
2722         case EOpBitShiftRight:
2723         case EOpBitShiftLeftAssign:
2724         case EOpBitShiftRightAssign:
2725                 // Unsigned can be bit-shifted by signed and vice versa, but we need to
2726                 // check that the basic type is an integer type.
2727                 isBitShift = true;
2728                 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
2729                 {
2730                         return false;
2731                 }
2732                 break;
2733         case EOpBitwiseAnd:
2734         case EOpBitwiseXor:
2735         case EOpBitwiseOr:
2736         case EOpBitwiseAndAssign:
2737         case EOpBitwiseXorAssign:
2738         case EOpBitwiseOrAssign:
2739                 // It is enough to check the type of only one operand, since later it
2740                 // is checked that the operand types match.
2741                 if(!IsInteger(left->getBasicType()))
2742                 {
2743                         return false;
2744                 }
2745                 break;
2746         default:
2747                 break;
2748         }
2749
2750         // GLSL ES 1.00 and 3.00 do not support implicit type casting.
2751         // So the basic type should usually match.
2752         if(!isBitShift && left->getBasicType() != right->getBasicType())
2753         {
2754                 return false;
2755         }
2756
2757         // Check that type sizes match exactly on ops that require that.
2758         // Also check restrictions for structs that contain arrays or samplers.
2759         switch(op)
2760         {
2761         case EOpAssign:
2762         case EOpInitialize:
2763         case EOpEqual:
2764         case EOpNotEqual:
2765                 // ESSL 1.00 sections 5.7, 5.8, 5.9
2766                 if(shaderVersion < 300 && left->getType().isStructureContainingArrays())
2767                 {
2768                         error(loc, "undefined operation for structs containing arrays", getOperatorString(op));
2769                         return false;
2770                 }
2771                 // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
2772                 // we interpret the spec so that this extends to structs containing samplers,
2773                 // similarly to ESSL 1.00 spec.
2774                 if((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
2775                         left->getType().isStructureContainingSamplers())
2776                 {
2777                         error(loc, "undefined operation for structs containing samplers", getOperatorString(op));
2778                         return false;
2779                 }
2780         case EOpLessThan:
2781         case EOpGreaterThan:
2782         case EOpLessThanEqual:
2783         case EOpGreaterThanEqual:
2784                 if((left->getNominalSize() != right->getNominalSize()) ||
2785                         (left->getSecondarySize() != right->getSecondarySize()))
2786                 {
2787                         return false;
2788                 }
2789         default:
2790                 break;
2791         }
2792
2793         return true;
2794 }
2795
2796 //
2797 // Parse an array of strings using yyparse.
2798 //
2799 // Returns 0 for success.
2800 //
2801 int PaParseStrings(int count, const char* const string[], const int length[],
2802                    TParseContext* context) {
2803     if ((count == 0) || (string == NULL))
2804         return 1;
2805
2806     if (glslang_initialize(context))
2807         return 1;
2808
2809     int error = glslang_scan(count, string, length, context);
2810     if (!error)
2811         error = glslang_parse(context);
2812
2813     glslang_finalize(context);
2814
2815     return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
2816 }
2817
2818
2819