Edit

kc3-lang/angle/src/compiler/translator/ParseContext.h

Branch :

  • Show log

    Commit

  • Author : Stuart Morgan
    Date : 2019-08-14 12:25:12
    Hash : 9d737966
    Message : Standardize copyright notices to project style For all "ANGLE Project" copyrights, standardize to the format specified by the style guide. Changes: - "Copyright (c)" and "Copyright(c)" changed to just "Copyright". - Removed the second half of date ranges ("Y1Y1-Y2Y2"->"Y1Y1"). - Fixed a small number of files that had no copyright date using the initial commit year from the version control history. - Fixed one instance of copyright being "The ANGLE Project" rather than "The ANGLE Project Authors" These changes are applied both to the copyright of source file, and where applicable to copyright statements that are generated by templates. BUG=angleproject:3811 Change-Id: I973dd65e4ef9deeba232d5be74c768256a0eb2e5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1754397 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/ParseContext.h
  • //
    // Copyright 2002 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    #ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_
    #define COMPILER_TRANSLATOR_PARSECONTEXT_H_
    
    #include "compiler/preprocessor/Preprocessor.h"
    #include "compiler/translator/Compiler.h"
    #include "compiler/translator/Declarator.h"
    #include "compiler/translator/Diagnostics.h"
    #include "compiler/translator/DirectiveHandler.h"
    #include "compiler/translator/FunctionLookup.h"
    #include "compiler/translator/QualifierTypes.h"
    #include "compiler/translator/SymbolTable.h"
    
    namespace sh
    {
    
    struct TMatrixFields
    {
        bool wholeRow;
        bool wholeCol;
        int row;
        int col;
    };
    
    //
    // The following are extra variables needed during parsing, grouped together so
    // they can be passed to the parser without needing a global.
    //
    class TParseContext : angle::NonCopyable
    {
      public:
        TParseContext(TSymbolTable &symt,
                      TExtensionBehavior &ext,
                      sh::GLenum type,
                      ShShaderSpec spec,
                      ShCompileOptions options,
                      bool checksPrecErrors,
                      TDiagnostics *diagnostics,
                      const ShBuiltInResources &resources);
        ~TParseContext();
    
        bool anyMultiviewExtensionAvailable();
        const angle::pp::Preprocessor &getPreprocessor() const { return mPreprocessor; }
        angle::pp::Preprocessor &getPreprocessor() { return mPreprocessor; }
        void *getScanner() const { return mScanner; }
        void setScanner(void *scanner) { mScanner = scanner; }
        int getShaderVersion() const { return mShaderVersion; }
        sh::GLenum getShaderType() const { return mShaderType; }
        ShShaderSpec getShaderSpec() const { return mShaderSpec; }
        int numErrors() const { return mDiagnostics->numErrors(); }
        void error(const TSourceLoc &loc, const char *reason, const char *token);
        void error(const TSourceLoc &loc, const char *reason, const ImmutableString &token);
        void warning(const TSourceLoc &loc, const char *reason, const char *token);
    
        // If isError is false, a warning will be reported instead.
        void outOfRangeError(bool isError,
                             const TSourceLoc &loc,
                             const char *reason,
                             const char *token);
    
        TIntermBlock *getTreeRoot() const { return mTreeRoot; }
        void setTreeRoot(TIntermBlock *treeRoot) { mTreeRoot = treeRoot; }
    
        bool getFragmentPrecisionHigh() const
        {
            return mFragmentPrecisionHighOnESSL1 || mShaderVersion >= 300;
        }
        void setFragmentPrecisionHighOnESSL1(bool fragmentPrecisionHigh)
        {
            mFragmentPrecisionHighOnESSL1 = fragmentPrecisionHigh;
        }
    
        void setLoopNestingLevel(int loopNestintLevel) { mLoopNestingLevel = loopNestintLevel; }
    
        void incrLoopNestingLevel() { ++mLoopNestingLevel; }
        void decrLoopNestingLevel() { --mLoopNestingLevel; }
    
        void incrSwitchNestingLevel() { ++mSwitchNestingLevel; }
        void decrSwitchNestingLevel() { --mSwitchNestingLevel; }
    
        bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; }
        sh::WorkGroupSize getComputeShaderLocalSize() const;
    
        int getNumViews() const { return mNumViews; }
    
        void enterFunctionDeclaration() { mDeclaringFunction = true; }
    
        void exitFunctionDeclaration() { mDeclaringFunction = false; }
    
        bool declaringFunction() const { return mDeclaringFunction; }
    
        TIntermConstantUnion *addScalarLiteral(const TConstantUnion *constantUnion,
                                               const TSourceLoc &line);
    
        // This method is guaranteed to succeed, even if no variable with 'name' exists.
        const TVariable *getNamedVariable(const TSourceLoc &location,
                                          const ImmutableString &name,
                                          const TSymbol *symbol);
        TIntermTyped *parseVariableIdentifier(const TSourceLoc &location,
                                              const ImmutableString &name,
                                              const TSymbol *symbol);
    
        // Look at a '.' field selector string and change it into offsets for a vector.
        bool parseVectorFields(const TSourceLoc &line,
                               const ImmutableString &compString,
                               int vecSize,
                               TVector<int> *fieldOffsets);
    
        void assignError(const TSourceLoc &line, const char *op, const TType &left, const TType &right);
        void unaryOpError(const TSourceLoc &line, const char *op, const TType &operand);
        void binaryOpError(const TSourceLoc &line,
                           const char *op,
                           const TType &left,
                           const TType &right);
    
        // Check functions - the ones that return bool return false if an error was generated.
    
        bool checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier);
        void checkPrecisionSpecified(const TSourceLoc &line, TPrecision precision, TBasicType type);
        bool checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node);
        void checkIsConst(TIntermTyped *node);
        void checkIsScalarInteger(TIntermTyped *node, const char *token);
        bool checkIsAtGlobalLevel(const TSourceLoc &line, const char *token);
        bool checkConstructorArguments(const TSourceLoc &line,
                                       const TIntermSequence &arguments,
                                       const TType &type);
    
        // Returns a sanitized array size to use (the size is at least 1).
        unsigned int checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr);
        bool checkIsValidQualifierForArray(const TSourceLoc &line, const TPublicType &elementQualifier);
        bool checkArrayElementIsNotArray(const TSourceLoc &line, const TPublicType &elementType);
        bool checkIsNonVoid(const TSourceLoc &line,
                            const ImmutableString &identifier,
                            const TBasicType &type);
        bool checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type);
        void checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType);
        bool checkIsNotOpaqueType(const TSourceLoc &line,
                                  const TTypeSpecifierNonArray &pType,
                                  const char *reason);
        void checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line, const TPublicType &pType);
        void checkLocationIsNotSpecified(const TSourceLoc &location,
                                         const TLayoutQualifier &layoutQualifier);
        void checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
                                                const TLayoutBlockStorage &blockStorage,
                                                const TQualifier &qualifier);
        void checkIsParameterQualifierValid(const TSourceLoc &line,
                                            const TTypeQualifierBuilder &typeQualifierBuilder,
                                            TType *type);
    
        // Check if at least one of the specified extensions can be used, and generate error/warning as
        // appropriate according to the spec.
        // This function is only needed for a few different small constant sizes of extension array, and
        // we want to avoid unnecessary dynamic allocations. That's why checkCanUseOneOfExtensions is a
        // template function rather than one taking a vector.
        template <size_t size>
        bool checkCanUseOneOfExtensions(const TSourceLoc &line,
                                        const std::array<TExtension, size> &extensions);
        bool checkCanUseExtension(const TSourceLoc &line, TExtension extension);
    
        // Done for all declarations, whether empty or not.
        void declarationQualifierErrorCheck(const sh::TQualifier qualifier,
                                            const sh::TLayoutQualifier &layoutQualifier,
                                            const TSourceLoc &location);
        // Done for the first non-empty declarator in a declaration.
        void nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
                                           const TSourceLoc &identifierLocation);
        // Done only for empty declarations.
        void emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location);
    
        void checkLayoutQualifierSupported(const TSourceLoc &location,
                                           const ImmutableString &layoutQualifierName,
                                           int versionRequired);
        bool checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
                                              const TLayoutQualifier &layoutQualifier);
        void functionCallRValueLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *fnCall);
        void checkInvariantVariableQualifier(bool invariant,
                                             const TQualifier qualifier,
                                             const TSourceLoc &invariantLocation);
        void checkInputOutputTypeIsValidES3(const TQualifier qualifier,
                                            const TPublicType &type,
                                            const TSourceLoc &qualifierLocation);
        void checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier);
        const TPragma &pragma() const { return mDirectiveHandler.pragma(); }
        const TExtensionBehavior &extensionBehavior() const
        {
            return mDirectiveHandler.extensionBehavior();
        }
    
        bool isExtensionEnabled(TExtension extension) const;
        void handleExtensionDirective(const TSourceLoc &loc, const char *extName, const char *behavior);
        void handlePragmaDirective(const TSourceLoc &loc,
                                   const char *name,
                                   const char *value,
                                   bool stdgl);
    
        // Returns true on success. *initNode may still be nullptr on success in case the initialization
        // is not needed in the AST.
        bool executeInitializer(const TSourceLoc &line,
                                const ImmutableString &identifier,
                                TType *type,
                                TIntermTyped *initializer,
                                TIntermBinary **initNode);
        TIntermNode *addConditionInitializer(const TPublicType &pType,
                                             const ImmutableString &identifier,
                                             TIntermTyped *initializer,
                                             const TSourceLoc &loc);
        TIntermNode *addLoop(TLoopType type,
                             TIntermNode *init,
                             TIntermNode *cond,
                             TIntermTyped *expr,
                             TIntermNode *body,
                             const TSourceLoc &loc);
    
        // For "if" test nodes. There are three children: a condition, a true path, and a false path.
        // The two paths are in TIntermNodePair code.
        TIntermNode *addIfElse(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &loc);
    
        void addFullySpecifiedType(TPublicType *typeSpecifier);
        TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
                                          const TPublicType &typeSpecifier);
    
        TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType,
                                                   const TSourceLoc &identifierOrTypeLocation,
                                                   const ImmutableString &identifier);
        TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &elementType,
                                                        const TSourceLoc &identifierLocation,
                                                        const ImmutableString &identifier,
                                                        const TSourceLoc &indexLocation,
                                                        const TVector<unsigned int> &arraySizes);
        TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
                                                       const TSourceLoc &identifierLocation,
                                                       const ImmutableString &identifier,
                                                       const TSourceLoc &initLocation,
                                                       TIntermTyped *initializer);
    
        // Parse a declaration like "type a[n] = initializer"
        // Note that this does not apply to declarations like "type[n] a = initializer"
        TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &elementType,
                                                            const TSourceLoc &identifierLocation,
                                                            const ImmutableString &identifier,
                                                            const TSourceLoc &indexLocation,
                                                            const TVector<unsigned int> &arraySizes,
                                                            const TSourceLoc &initLocation,
                                                            TIntermTyped *initializer);
    
        TIntermInvariantDeclaration *parseInvariantDeclaration(
            const TTypeQualifierBuilder &typeQualifierBuilder,
            const TSourceLoc &identifierLoc,
            const ImmutableString &identifier,
            const TSymbol *symbol);
    
        void parseDeclarator(TPublicType &publicType,
                             const TSourceLoc &identifierLocation,
                             const ImmutableString &identifier,
                             TIntermDeclaration *declarationOut);
        void parseArrayDeclarator(TPublicType &elementType,
                                  const TSourceLoc &identifierLocation,
                                  const ImmutableString &identifier,
                                  const TSourceLoc &arrayLocation,
                                  const TVector<unsigned int> &arraySizes,
                                  TIntermDeclaration *declarationOut);
        void parseInitDeclarator(const TPublicType &publicType,
                                 const TSourceLoc &identifierLocation,
                                 const ImmutableString &identifier,
                                 const TSourceLoc &initLocation,
                                 TIntermTyped *initializer,
                                 TIntermDeclaration *declarationOut);
    
        // Parse a declarator like "a[n] = initializer"
        void parseArrayInitDeclarator(const TPublicType &elementType,
                                      const TSourceLoc &identifierLocation,
                                      const ImmutableString &identifier,
                                      const TSourceLoc &indexLocation,
                                      const TVector<unsigned int> &arraySizes,
                                      const TSourceLoc &initLocation,
                                      TIntermTyped *initializer,
                                      TIntermDeclaration *declarationOut);
    
        TIntermNode *addEmptyStatement(const TSourceLoc &location);
    
        void parseDefaultPrecisionQualifier(const TPrecision precision,
                                            const TPublicType &type,
                                            const TSourceLoc &loc);
        void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
    
        TIntermFunctionPrototype *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
                                                                  const TSourceLoc &location);
        TIntermFunctionDefinition *addFunctionDefinition(TIntermFunctionPrototype *functionPrototype,
                                                         TIntermBlock *functionBody,
                                                         const TSourceLoc &location);
        void parseFunctionDefinitionHeader(const TSourceLoc &location,
                                           const TFunction *function,
                                           TIntermFunctionPrototype **prototypeOut);
        TFunction *parseFunctionDeclarator(const TSourceLoc &location, TFunction *function);
        TFunction *parseFunctionHeader(const TPublicType &type,
                                       const ImmutableString &name,
                                       const TSourceLoc &location);
    
        TFunctionLookup *addNonConstructorFunc(const ImmutableString &name, const TSymbol *symbol);
        TFunctionLookup *addConstructorFunc(const TPublicType &publicType);
    
        TParameter parseParameterDeclarator(const TPublicType &publicType,
                                            const ImmutableString &name,
                                            const TSourceLoc &nameLoc);
    
        TParameter parseParameterArrayDeclarator(const ImmutableString &name,
                                                 const TSourceLoc &nameLoc,
                                                 const TVector<unsigned int> &arraySizes,
                                                 const TSourceLoc &arrayLoc,
                                                 TPublicType *elementType);
    
        TIntermTyped *addIndexExpression(TIntermTyped *baseExpression,
                                         const TSourceLoc &location,
                                         TIntermTyped *indexExpression);
        TIntermTyped *addFieldSelectionExpression(TIntermTyped *baseExpression,
                                                  const TSourceLoc &dotLocation,
                                                  const ImmutableString &fieldString,
                                                  const TSourceLoc &fieldLocation);
    
        // Parse declarator for a single field
        TDeclarator *parseStructDeclarator(const ImmutableString &identifier, const TSourceLoc &loc);
        TDeclarator *parseStructArrayDeclarator(const ImmutableString &identifier,
                                                const TSourceLoc &loc,
                                                const TVector<unsigned int> *arraySizes);
    
        void checkDoesNotHaveDuplicateFieldName(const TFieldList::const_iterator begin,
                                                const TFieldList::const_iterator end,
                                                const ImmutableString &name,
                                                const TSourceLoc &location);
        TFieldList *addStructFieldList(TFieldList *fields, const TSourceLoc &location);
        TFieldList *combineStructFieldLists(TFieldList *processedFields,
                                            const TFieldList *newlyAddedFields,
                                            const TSourceLoc &location);
        TFieldList *addStructDeclaratorListWithQualifiers(
            const TTypeQualifierBuilder &typeQualifierBuilder,
            TPublicType *typeSpecifier,
            const TDeclaratorList *declaratorList);
        TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier,
                                            const TDeclaratorList *declaratorList);
        TTypeSpecifierNonArray addStructure(const TSourceLoc &structLine,
                                            const TSourceLoc &nameLine,
                                            const ImmutableString &structName,
                                            TFieldList *fieldList);
    
        TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
                                              const TSourceLoc &nameLine,
                                              const ImmutableString &blockName,
                                              TFieldList *fieldList,
                                              const ImmutableString &instanceName,
                                              const TSourceLoc &instanceLine,
                                              TIntermTyped *arrayIndex,
                                              const TSourceLoc &arrayIndexLine);
    
        void parseLocalSize(const ImmutableString &qualifierType,
                            const TSourceLoc &qualifierTypeLine,
                            int intValue,
                            const TSourceLoc &intValueLine,
                            const std::string &intValueString,
                            size_t index,
                            sh::WorkGroupSize *localSize);
        void parseNumViews(int intValue,
                           const TSourceLoc &intValueLine,
                           const std::string &intValueString,
                           int *numViews);
        void parseInvocations(int intValue,
                              const TSourceLoc &intValueLine,
                              const std::string &intValueString,
                              int *numInvocations);
        void parseMaxVertices(int intValue,
                              const TSourceLoc &intValueLine,
                              const std::string &intValueString,
                              int *numMaxVertices);
        void parseIndexLayoutQualifier(int intValue,
                                       const TSourceLoc &intValueLine,
                                       const std::string &intValueString,
                                       int *index);
        TLayoutQualifier parseLayoutQualifier(const ImmutableString &qualifierType,
                                              const TSourceLoc &qualifierTypeLine);
        TLayoutQualifier parseLayoutQualifier(const ImmutableString &qualifierType,
                                              const TSourceLoc &qualifierTypeLine,
                                              int intValue,
                                              const TSourceLoc &intValueLine);
        TTypeQualifierBuilder *createTypeQualifierBuilder(const TSourceLoc &loc);
        TStorageQualifierWrapper *parseGlobalStorageQualifier(TQualifier qualifier,
                                                              const TSourceLoc &loc);
        TStorageQualifierWrapper *parseVaryingQualifier(const TSourceLoc &loc);
        TStorageQualifierWrapper *parseInQualifier(const TSourceLoc &loc);
        TStorageQualifierWrapper *parseOutQualifier(const TSourceLoc &loc);
        TStorageQualifierWrapper *parseInOutQualifier(const TSourceLoc &loc);
        TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier,
                                              TLayoutQualifier rightQualifier,
                                              const TSourceLoc &rightQualifierLocation);
    
        // Performs an error check for embedded struct declarations.
        void enterStructDeclaration(const TSourceLoc &line, const ImmutableString &identifier);
        void exitStructDeclaration();
    
        void checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field);
    
        TIntermSwitch *addSwitch(TIntermTyped *init,
                                 TIntermBlock *statementList,
                                 const TSourceLoc &loc);
        TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
        TIntermCase *addDefault(const TSourceLoc &loc);
    
        TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
        TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc);
        TIntermTyped *addBinaryMath(TOperator op,
                                    TIntermTyped *left,
                                    TIntermTyped *right,
                                    const TSourceLoc &loc);
        TIntermTyped *addBinaryMathBooleanResult(TOperator op,
                                                 TIntermTyped *left,
                                                 TIntermTyped *right,
                                                 const TSourceLoc &loc);
        TIntermTyped *addAssign(TOperator op,
                                TIntermTyped *left,
                                TIntermTyped *right,
                                const TSourceLoc &loc);
    
        TIntermTyped *addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
    
        TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
        TIntermBranch *addBranch(TOperator op, TIntermTyped *expression, const TSourceLoc &loc);
    
        void appendStatement(TIntermBlock *block, TIntermNode *statement);
    
        void checkTextureGather(TIntermAggregate *functionCall);
        void checkTextureOffsetConst(TIntermAggregate *functionCall);
        void checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall);
        void checkImageMemoryAccessForUserDefinedFunctions(const TFunction *functionDefinition,
                                                           const TIntermAggregate *functionCall);
        void checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall);
    
        // fnCall is only storing the built-in op, and function name or constructor type. arguments
        // has the arguments.
        TIntermTyped *addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
    
        TIntermTyped *addTernarySelection(TIntermTyped *cond,
                                          TIntermTyped *trueExpression,
                                          TIntermTyped *falseExpression,
                                          const TSourceLoc &line);
    
        int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
        int getGeometryShaderInvocations() const
        {
            return (mGeometryShaderInvocations > 0) ? mGeometryShaderInvocations : 1;
        }
        TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const
        {
            return mGeometryShaderInputPrimitiveType;
        }
        TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const
        {
            return mGeometryShaderOutputPrimitiveType;
        }
    
        // TODO(jmadill): make this private
        TSymbolTable &symbolTable;  // symbol table that goes with the language currently being parsed
    
      private:
        class AtomicCounterBindingState;
        constexpr static size_t kAtomicCounterSize = 4;
        // UNIFORM_ARRAY_STRIDE for atomic counter arrays is an implementation-dependent value which
        // can be queried after a program is linked according to ES 3.10 section 7.7.1. This is
        // controversial with the offset inheritance as described in ESSL 3.10 section 4.4.6. Currently
        // we treat it as always 4 in favour of the original interpretation in
        // "ARB_shader_atomic_counters".
        // TODO(jie.a.chen@intel.com): Double check this once the spec vagueness is resolved.
        // Note that there may be tests in AtomicCounter_test that will need to be updated as well.
        constexpr static size_t kAtomicCounterArrayStride = 4;
    
        void markStaticReadIfSymbol(TIntermNode *node);
    
        // Returns a clamped index. If it prints out an error message, the token is "[]".
        int checkIndexLessThan(bool outOfRangeIndexIsError,
                               const TSourceLoc &location,
                               int index,
                               int arraySize,
                               const char *reason);
    
        bool declareVariable(const TSourceLoc &line,
                             const ImmutableString &identifier,
                             const TType *type,
                             TVariable **variable);
    
        void checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
                                                  const ImmutableString &identifier,
                                                  TType *type);
    
        TParameter parseParameterDeclarator(TType *type,
                                            const ImmutableString &name,
                                            const TSourceLoc &nameLoc);
    
        bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
                                                  const TPublicType &elementType);
        // Done for all atomic counter declarations, whether empty or not.
        void atomicCounterQualifierErrorCheck(const TPublicType &publicType,
                                              const TSourceLoc &location);
    
        // Assumes that multiplication op has already been set based on the types.
        bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right);
    
        void checkOutParameterIsNotOpaqueType(const TSourceLoc &line,
                                              TQualifier qualifier,
                                              const TType &type);
    
        void checkInternalFormatIsNotSpecified(const TSourceLoc &location,
                                               TLayoutImageInternalFormat internalFormat);
        void checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
                                                const TSourceLoc &location);
        void checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
                                                    const TSourceLoc &loc,
                                                    TType *type);
        void checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type);
    
        void checkIndexIsNotSpecified(const TSourceLoc &location, int index);
        void checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type);
        void checkBindingIsNotSpecified(const TSourceLoc &location, int binding);
        void checkOffsetIsNotSpecified(const TSourceLoc &location, int offset);
        void checkImageBindingIsValid(const TSourceLoc &location,
                                      int binding,
                                      int arrayTotalElementCount);
        void checkSamplerBindingIsValid(const TSourceLoc &location,
                                        int binding,
                                        int arrayTotalElementCount);
        void checkBlockBindingIsValid(const TSourceLoc &location,
                                      const TQualifier &qualifier,
                                      int binding,
                                      int arraySize);
        void checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding);
    
        void checkUniformLocationInRange(const TSourceLoc &location,
                                         int objectLocationCount,
                                         const TLayoutQualifier &layoutQualifier);
    
        void checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv);
    
        bool checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence &arguments,
                                                                TType type,
                                                                const TSourceLoc &line);
    
        // Will set the size of the outermost array according to geometry shader input layout.
        void checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
                                                     const ImmutableString &token,
                                                     TType *type);
    
        // Will size any unsized array type so unsized arrays won't need to be taken into account
        // further along the line in parsing.
        void checkIsNotUnsizedArray(const TSourceLoc &line,
                                    const char *errorMessage,
                                    const ImmutableString &token,
                                    TType *arrayType);
    
        TIntermTyped *addBinaryMathInternal(TOperator op,
                                            TIntermTyped *left,
                                            TIntermTyped *right,
                                            const TSourceLoc &loc);
        TIntermTyped *createUnaryMath(TOperator op,
                                      TIntermTyped *child,
                                      const TSourceLoc &loc,
                                      const TFunction *func);
    
        TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
        TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line);
        TIntermTyped *addNonConstructorFunctionCall(TFunctionLookup *fnCall, const TSourceLoc &loc);
    
        // Return either the original expression or the folded version of the expression in case the
        // folded node will validate the same way during subsequent parsing.
        TIntermTyped *expressionOrFoldedResult(TIntermTyped *expression);
    
        // Return true if the checks pass
        bool binaryOpCommonCheck(TOperator op,
                                 TIntermTyped *left,
                                 TIntermTyped *right,
                                 const TSourceLoc &loc);
    
        TIntermFunctionPrototype *createPrototypeNodeFromFunction(const TFunction &function,
                                                                  const TSourceLoc &location,
                                                                  bool insertParametersToSymbolTable);
    
        void setAtomicCounterBindingDefaultOffset(const TPublicType &declaration,
                                                  const TSourceLoc &location);
    
        bool checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier);
        bool parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier);
        bool parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier);
        void setGeometryShaderInputArraySize(unsigned int inputArraySize, const TSourceLoc &line);
    
        // Set to true when the last/current declarator list was started with an empty declaration. The
        // non-empty declaration error check will need to be performed if the empty declaration is
        // followed by a declarator.
        bool mDeferredNonEmptyDeclarationErrorCheck;
    
        sh::GLenum mShaderType;    // vertex or fragment language (future: pack or unpack)
        ShShaderSpec mShaderSpec;  // The language specification compiler conforms to - GLES2 or WebGL.
        ShCompileOptions mCompileOptions;  // Options passed to TCompiler
        int mShaderVersion;
        TIntermBlock *mTreeRoot;  // root of parse tree being created
        int mLoopNestingLevel;    // 0 if outside all loops
        int mStructNestingLevel;  // incremented while parsing a struct declaration
        int mSwitchNestingLevel;  // 0 if outside all switch statements
        const TType
            *mCurrentFunctionType;    // the return type of the function that's currently being parsed
        bool mFunctionReturnsValue;   // true if a non-void function has a return
        bool mChecksPrecisionErrors;  // true if an error will be generated when a variable is declared
                                      // without precision, explicit or implicit.
        bool mFragmentPrecisionHighOnESSL1;  // true if highp precision is supported when compiling
                                             // ESSL1.
        TLayoutMatrixPacking mDefaultUniformMatrixPacking;
        TLayoutBlockStorage mDefaultUniformBlockStorage;
        TLayoutMatrixPacking mDefaultBufferMatrixPacking;
        TLayoutBlockStorage mDefaultBufferBlockStorage;
        TString mHashErrMsg;
        TDiagnostics *mDiagnostics;
        TDirectiveHandler mDirectiveHandler;
        angle::pp::Preprocessor mPreprocessor;
        void *mScanner;
        int mMinProgramTexelOffset;
        int mMaxProgramTexelOffset;
    
        int mMinProgramTextureGatherOffset;
        int mMaxProgramTextureGatherOffset;
    
        // keep track of local group size declared in layout. It should be declared only once.
        bool mComputeShaderLocalSizeDeclared;
        sh::WorkGroupSize mComputeShaderLocalSize;
        // keep track of number of views declared in layout.
        int mNumViews;
        int mMaxNumViews;
        int mMaxImageUnits;
        int mMaxCombinedTextureImageUnits;
        int mMaxUniformLocations;
        int mMaxUniformBufferBindings;
        int mMaxAtomicCounterBindings;
        int mMaxShaderStorageBufferBindings;
    
        // keeps track whether we are declaring / defining a function
        bool mDeclaringFunction;
    
        // Track the state of each atomic counter binding.
        std::map<int, AtomicCounterBindingState> mAtomicCounterBindingStates;
    
        // Track the geometry shader global parameters declared in layout.
        TLayoutPrimitiveType mGeometryShaderInputPrimitiveType;
        TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType;
        int mGeometryShaderInvocations;
        int mGeometryShaderMaxVertices;
        int mMaxGeometryShaderInvocations;
        int mMaxGeometryShaderMaxVertices;
    
        // Track when we add new scope for func body in ESSL 1.00 spec
        bool mFunctionBodyNewScope;
    };
    
    int PaParseStrings(size_t count,
                       const char *const string[],
                       const int length[],
                       TParseContext *context);
    
    }  // namespace sh
    
    #endif  // COMPILER_TRANSLATOR_PARSECONTEXT_H_